123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ppapi/tests/test_fullscreen.h"
- #include <stdio.h>
- #include <string.h>
- #include <string>
- #include "ppapi/c/ppb_fullscreen.h"
- #include "ppapi/cpp/image_data.h"
- #include "ppapi/cpp/input_event.h"
- #include "ppapi/cpp/instance.h"
- #include "ppapi/cpp/module.h"
- #include "ppapi/cpp/point.h"
- #include "ppapi/tests/test_utils.h"
- #include "ppapi/tests/testing_instance.h"
- REGISTER_TEST_CASE(Fullscreen);
- namespace {
- const ColorPremul kSheerBlue = { 0x88, 0x00, 0x00, 0x88 };
- const ColorPremul kOpaqueYellow = { 0xFF, 0xFF, 0xFF, 0x00 };
- const int kBytesPerPixel = sizeof(uint32_t); // 4 bytes for BGRA or RGBA.
- uint32_t FormatColor(PP_ImageDataFormat format, ColorPremul color) {
- if (format == PP_IMAGEDATAFORMAT_BGRA_PREMUL)
- return (color.A << 24) | (color.R << 16) | (color.G << 8) | (color.B);
- else if (format == PP_IMAGEDATAFORMAT_RGBA_PREMUL)
- return (color.A << 24) | (color.B << 16) | (color.G << 8) | (color.R);
- else
- return 0;
- }
- bool HasMidScreen(const pp::Rect& position, const pp::Size& screen_size) {
- static int32_t mid_x = screen_size.width() / 2;
- static int32_t mid_y = screen_size.height() / 2;
- return (position.Contains(mid_x, mid_y));
- }
- void FlushCallbackCheckImageData(void* data, int32_t result) {
- static_cast<TestFullscreen*>(data)->CheckPluginPaint();
- }
- } // namespace
- TestFullscreen::TestFullscreen(TestingInstance* instance)
- : TestCase(instance),
- error_(),
- screen_mode_(instance),
- painted_color_(0),
- fullscreen_pending_(false),
- normal_pending_(false),
- fullscreen_event_(instance->pp_instance()),
- normal_event_(instance->pp_instance()) {
- screen_mode_.GetScreenSize(&screen_size_);
- }
- bool TestFullscreen::Init() {
- if (screen_size_.IsEmpty()) {
- instance_->AppendError("Failed to initialize screen_size_");
- return false;
- }
- graphics2d_ = pp::Graphics2D(instance_, screen_size_, true);
- if (!instance_->BindGraphics(graphics2d_)) {
- instance_->AppendError("Failed to initialize graphics2d_");
- return false;
- }
- return CheckTestingInterface();
- }
- void TestFullscreen::RunTests(const std::string& filter) {
- RUN_TEST(GetScreenSize, filter);
- RUN_TEST(NormalToFullscreenToNormal, filter);
- }
- bool TestFullscreen::GotError() {
- return !error_.empty();
- }
- std::string TestFullscreen::Error() {
- std::string last_error = error_;
- error_.clear();
- return last_error;
- }
- // TODO(polina): consider adding custom logic to JS for this test to
- // get screen.width and screen.height and postMessage those to this code,
- // so the dimensions can be checked exactly.
- std::string TestFullscreen::TestGetScreenSize() {
- if (screen_size_.width() < 320 || screen_size_.width() > 2560)
- return ReportError("screen_size.width()", screen_size_.width());
- if (screen_size_.height() < 200 || screen_size_.height() > 2048)
- return ReportError("screen_size.height()", screen_size_.height());
- PASS();
- }
- std::string TestFullscreen::TestNormalToFullscreenToNormal() {
- // 0. Start in normal mode.
- if (screen_mode_.IsFullscreen())
- return ReportError("IsFullscreen() at start", true);
- // 1. Switch to fullscreen.
- // This is only allowed within a context of a user gesture (e.g. mouse click).
- if (screen_mode_.SetFullscreen(true))
- return ReportError("SetFullscreen(true) outside of user gesture", true);
- // Trigger another call to SetFullscreen(true) from HandleInputEvent().
- // The transition is asynchronous and ends at the next DidChangeView().
- instance_->RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
- SimulateUserGesture();
- // DidChangeView() will call the callback once in fullscreen mode.
- fullscreen_event_.Wait();
- if (GotError())
- return Error();
- if (fullscreen_pending_)
- return "fullscreen_pending_ has not been reset";
- if (!screen_mode_.IsFullscreen())
- return ReportError("IsFullscreen() in fullscreen", false);
- // 2. Stay in fullscreen. No change.
- if (screen_mode_.SetFullscreen(true))
- return ReportError("SetFullscreen(true) in fullscreen", true);
- if (!screen_mode_.IsFullscreen())
- return ReportError("IsFullscreen() in fullscreen^2", false);
- // 3. Switch to normal.
- // The transition is asynchronous and ends at DidChangeView().
- // No graphics devices can be bound while in transition.
- normal_pending_ = true;
- if (!screen_mode_.SetFullscreen(false))
- return ReportError("SetFullscreen(false) in fullscreen", false);
- // DidChangeView() will signal once out of fullscreen mode.
- normal_event_.Wait();
- if (GotError())
- return Error();
- if (normal_pending_)
- return "normal_pending_ has not been reset";
- if (screen_mode_.IsFullscreen())
- return ReportError("IsFullscreen() in normal", true);
- // 4. Stay in normal. No change.
- if (screen_mode_.SetFullscreen(false))
- return ReportError("SetFullscreen(false) in normal", true);
- if (screen_mode_.IsFullscreen())
- return ReportError("IsFullscreen() in normal^2", true);
- PASS();
- }
- void TestFullscreen::SimulateUserGesture() {
- pp::Point plugin_center(
- normal_position_.x() + normal_position_.width() / 2,
- normal_position_.y() + normal_position_.height() / 2);
- pp::Point mouse_movement;
- pp::MouseInputEvent input_event(
- instance_,
- PP_INPUTEVENT_TYPE_MOUSEDOWN,
- NowInTimeTicks(), // time_stamp
- 0, // modifiers
- PP_INPUTEVENT_MOUSEBUTTON_LEFT,
- plugin_center,
- 1, // click_count
- mouse_movement);
- testing_interface_->SimulateInputEvent(instance_->pp_instance(),
- input_event.pp_resource());
- }
- void TestFullscreen::FailFullscreenTest(const std::string& error) {
- error_ = error;
- fullscreen_event_.Signal();
- }
- void TestFullscreen::FailNormalTest(const std::string& error) {
- error_ = error;
- normal_event_.Signal();
- }
- void TestFullscreen::PassFullscreenTest() {
- fullscreen_event_.Signal();
- }
- void TestFullscreen::PassNormalTest() {
- normal_event_.Signal();
- }
- // Transition to fullscreen can only happen when processing a user gesture.
- bool TestFullscreen::HandleInputEvent(const pp::InputEvent& event) {
- // We only let mouse events through and only mouse clicks count.
- if (event.GetType() != PP_INPUTEVENT_TYPE_MOUSEDOWN &&
- event.GetType() != PP_INPUTEVENT_TYPE_MOUSEUP)
- return false;
- // We got the gesture. No need to handle any more events.
- instance_->ClearInputEventRequest(PP_INPUTEVENT_CLASS_MOUSE);
- if (screen_mode_.IsFullscreen()) {
- FailFullscreenTest(
- ReportError("IsFullscreen() before fullscreen transition", true));
- return false;
- }
- fullscreen_pending_ = true;
- if (!screen_mode_.SetFullscreen(true)) {
- FailFullscreenTest(ReportError("SetFullscreen(true) in normal", false));
- return false;
- }
- // DidChangeView() will complete the transition to fullscreen.
- return false;
- }
- bool TestFullscreen::PaintPlugin(pp::Size size, ColorPremul color) {
- painted_size_ = size;
- PP_ImageDataFormat image_format = pp::ImageData::GetNativeImageDataFormat();
- painted_color_ = FormatColor(image_format, color);
- if (painted_color_ == 0)
- return false;
- pp::Point origin(0, 0);
- pp::ImageData image(instance_, image_format, size, false);
- if (image.is_null())
- return false;
- uint32_t* pixels = static_cast<uint32_t*>(image.data());
- int num_pixels = image.stride() / kBytesPerPixel * image.size().height();
- for (int i = 0; i < num_pixels; i++)
- pixels[i] = painted_color_;
- graphics2d_.PaintImageData(image, origin);
- pp::CompletionCallback cc(FlushCallbackCheckImageData, this);
- if (graphics2d_.Flush(cc) != PP_OK_COMPLETIONPENDING)
- return false;
- return true;
- }
- void TestFullscreen::CheckPluginPaint() {
- PP_ImageDataFormat image_format = pp::ImageData::GetNativeImageDataFormat();
- pp::ImageData readback(instance_, image_format, painted_size_, false);
- pp::Point origin(0, 0);
- if (readback.is_null() ||
- PP_TRUE != testing_interface_->ReadImageData(graphics2d_.pp_resource(),
- readback.pp_resource(),
- &origin.pp_point())) {
- error_ = "Can't read plugin image";
- return;
- }
- for (int y = 0; y < painted_size_.height(); y++) {
- for (int x = 0; x < painted_size_.width(); x++) {
- uint32_t* readback_color = readback.GetAddr32(pp::Point(x, y));
- if (painted_color_ != *readback_color) {
- error_ = "Plugin image contains incorrect pixel value";
- return;
- }
- }
- }
- if (screen_mode_.IsFullscreen())
- PassFullscreenTest();
- else
- PassNormalTest();
- }
- // Transitions to/from fullscreen is asynchronous ending at DidChangeView.
- // The number of calls to DidChangeView during fullscreen / normal transitions
- // isn't specified by the API. The test waits until it the screen has
- // transitioned to the desired state.
- //
- // WebKit does not change the plugin size, but Pepper does explicitly set
- // it to screen width and height when SetFullscreen(true) is called and
- // resets it back when ViewChanged is received indicating that we exited
- // fullscreen.
- //
- // NOTE: The number of DidChangeView calls for <object> might be different.
- // TODO(bbudge) Figure out how to test that the plugin positon eventually
- // changes to normal_position_.
- void TestFullscreen::DidChangeView(const pp::View& view) {
- pp::Rect position = view.GetRect();
- pp::Rect clip = view.GetClipRect();
- if (normal_position_.IsEmpty())
- normal_position_ = position;
- bool is_fullscreen = screen_mode_.IsFullscreen();
- if (fullscreen_pending_ && is_fullscreen) {
- fullscreen_pending_ = false;
- if (!HasMidScreen(position, screen_size_))
- FailFullscreenTest("DidChangeView is not in the middle of the screen");
- else if (position.size() != screen_size_)
- FailFullscreenTest("DidChangeView does not have screen size");
- // NOTE: we cannot reliably test for clip size being equal to the screen
- // because it might be affected by JS console, info bars, etc.
- else if (!instance_->BindGraphics(graphics2d_))
- FailFullscreenTest("Failed to BindGraphics() in fullscreen");
- else if (!PaintPlugin(position.size(), kOpaqueYellow))
- FailFullscreenTest("Failed to paint plugin image in fullscreen");
- } else if (normal_pending_ && !is_fullscreen) {
- normal_pending_ = false;
- if (screen_mode_.IsFullscreen())
- FailNormalTest("DidChangeview is in fullscreen");
- else if (!instance_->BindGraphics(graphics2d_))
- FailNormalTest("Failed to BindGraphics() in normal");
- else if (!PaintPlugin(position.size(), kSheerBlue))
- FailNormalTest("Failed to paint plugin image in normal");
- }
- }
|