diff options
author | polina@google.com <polina@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-14 09:24:43 +0000 |
---|---|---|
committer | polina@google.com <polina@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-14 09:24:43 +0000 |
commit | a2706da6dc6ea7346b0276218303de192f6b5362 (patch) | |
tree | 02ba51e8c4db3fcc8e0b46527c4cb90ce89aa54c | |
parent | b7bd3d4658875c6d9c70c032dcd0601bd1b0bf6a (diff) | |
download | chromium_src-a2706da6dc6ea7346b0276218303de192f6b5362.zip chromium_src-a2706da6dc6ea7346b0276218303de192f6b5362.tar.gz chromium_src-a2706da6dc6ea7346b0276218303de192f6b5362.tar.bz2 |
PPAPI Fullscreen: Hack plugin's attributes to force resizing of the plugin to fill in the screen in SetFullscreen. Reset plugin size in ViewChanged when we exit. Update tests.
We are forced to resize the plugin in the Pepper layer because WebKit does yet do it.
It only moves the plugin to the middle of the screen with the expectations the
web page will contain the following css:
:-webkit-full-screen {
width: 100%; height: 100%;
}
That's not acceptable for Pepper/NaCl users.
BUG=41780,98474
TEST=in CL
Review URL: http://codereview.chromium.org/8228023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105476 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ppapi/api/dev/ppb_fullscreen_dev.idl | 10 | ||||
-rw-r--r-- | ppapi/c/dev/ppb_fullscreen_dev.h | 12 | ||||
-rw-r--r-- | ppapi/native_client/tests/ppapi_browser/ppb_fullscreen/ppapi_ppb_fullscreen.cc | 26 | ||||
-rw-r--r-- | ppapi/tests/test_fullscreen.cc | 16 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppapi_plugin_instance.cc | 99 | ||||
-rw-r--r-- | webkit/plugins/ppapi/ppapi_plugin_instance.h | 19 |
6 files changed, 139 insertions, 43 deletions
diff --git a/ppapi/api/dev/ppb_fullscreen_dev.idl b/ppapi/api/dev/ppb_fullscreen_dev.idl index 028cda6..0fd6373 100644 --- a/ppapi/api/dev/ppb_fullscreen_dev.idl +++ b/ppapi/api/dev/ppb_fullscreen_dev.idl @@ -27,14 +27,12 @@ interface PPB_Fullscreen_Dev { * will execute as if the resource was off-screen. The transition to and from * fullscreen is asynchronous. During the transition, IsFullscreen will * return the original value, and no 2D or 3D device can be bound. - * The transition ends at the next DidChangeView. + * The transition ends at DidChangeView when IsFullscreen returns the new + * value. You might receive other DidChangeView calls while in + * transition. * * The transition to fullscreen can only occur while the browser is - * processing a user gesture, even if PP_TRUE is returned. Note that two - * DidChangeView calls will happen when switching to fullscreen: - * one for moving the plugin to the middle of the window and one for - * stretching the window placing the plugin in the middle of the screen. - * Plugin size will not be affected. + * processing a user gesture, even if PP_TRUE is returned. */ PP_Bool SetFullscreen( [in] PP_Instance instance, diff --git a/ppapi/c/dev/ppb_fullscreen_dev.h b/ppapi/c/dev/ppb_fullscreen_dev.h index bae1497..5022c2a 100644 --- a/ppapi/c/dev/ppb_fullscreen_dev.h +++ b/ppapi/c/dev/ppb_fullscreen_dev.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From dev/ppb_fullscreen_dev.idl modified Mon Sep 26 15:06:40 2011. */ +/* From dev/ppb_fullscreen_dev.idl modified Tue Oct 11 15:45:41 2011. */ #ifndef PPAPI_C_DEV_PPB_FULLSCREEN_DEV_H_ #define PPAPI_C_DEV_PPB_FULLSCREEN_DEV_H_ @@ -40,14 +40,12 @@ struct PPB_Fullscreen_Dev { * will execute as if the resource was off-screen. The transition to and from * fullscreen is asynchronous. During the transition, IsFullscreen will * return the original value, and no 2D or 3D device can be bound. - * The transition ends at the next DidChangeView. + * The transition ends at DidChangeView when IsFullscreen returns the new + * value. You might receive other DidChangeView calls while in + * transition. * * The transition to fullscreen can only occur while the browser is - * processing a user gesture, even if PP_TRUE is returned. Note that two - * DidChangeView calls will happen when switching to fullscreen: - * one for moving the plugin to the middle of the window and one for - * stretching the window placing the plugin in the middle of the screen. - * Plugin size will not be affected. + * processing a user gesture, even if PP_TRUE is returned. */ PP_Bool (*SetFullscreen)(PP_Instance instance, PP_Bool fullscreen); /** diff --git a/ppapi/native_client/tests/ppapi_browser/ppb_fullscreen/ppapi_ppb_fullscreen.cc b/ppapi/native_client/tests/ppapi_browser/ppb_fullscreen/ppapi_ppb_fullscreen.cc index 4a87752..333605e 100644 --- a/ppapi/native_client/tests/ppapi_browser/ppb_fullscreen/ppapi_ppb_fullscreen.cc +++ b/ppapi/native_client/tests/ppapi_browser/ppb_fullscreen/ppapi_ppb_fullscreen.cc @@ -221,11 +221,8 @@ bool HasMidScreen(const PP_Rect* position) { } // DidChangeView completes transition to/from fullscreen mode. -// In fact, we get two of them when going to fullscreen, one when the plugin -// is placed in the middle of the window and one when the window is resized, -// placing the plugin in the middle of the screen. -// The size of the plugin is not affected. -bool g_saw_first_didchangeview = false; +// The plugin is resized to the size of the screen. +// NOTE: The number of DidChangeView calls for <object> might be different. PP_Rect g_normal_position = PP_MakeRectFromXYWH(0, 0, 0, 0); void DidChangeView(PP_Instance instance, const struct PP_Rect* position, @@ -247,22 +244,17 @@ void DidChangeView(PP_Instance instance, } const char* test = NULL; - if (g_fullscreen_pending && !g_saw_first_didchangeview) { - g_saw_first_didchangeview = true; - EXPECT(PPBFullscreenDev()->IsFullscreen(pp_instance()) == PP_TRUE); - EXPECT(IsSizeEqual(position->size, g_normal_position.size)); - // Wait for the 2nd DidChangeView. - } else if (g_fullscreen_pending) { + PP_Size screen_size = GetScreenSize(); + if (g_fullscreen_pending && PPBFullscreenDev()->IsFullscreen(pp_instance())) { test = "TestSetFullscreenTrue"; g_fullscreen_pending = false; - g_saw_first_didchangeview = false; // Reset. - EXPECT(PPBFullscreenDev()->IsFullscreen(pp_instance()) == PP_TRUE); - EXPECT(HasMidScreen(position)); - EXPECT(IsSizeEqual(position->size, g_normal_position.size)); - } else if (g_normal_pending) { + EXPECT(IsSizeEqual(position->size, 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 (g_normal_pending && + !PPBFullscreenDev()->IsFullscreen(pp_instance())) { test = "TestSetFullscreenFalse"; g_normal_pending = false; - EXPECT(PPBFullscreenDev()->IsFullscreen(pp_instance()) == PP_FALSE); EXPECT(IsRectEqual(*position, g_normal_position)); } if (test != NULL) { diff --git a/ppapi/tests/test_fullscreen.cc b/ppapi/tests/test_fullscreen.cc index 95a0dd7..6963aaf 100644 --- a/ppapi/tests/test_fullscreen.cc +++ b/ppapi/tests/test_fullscreen.cc @@ -185,7 +185,11 @@ bool TestFullscreen::HandleInputEvent(const pp::InputEvent& event) { // When going to fullscreen, two DidChangeView calls are generated: // one for moving the plugin to the middle of window and one for stretching // the window and placing the plugin in the middle of the screen. -// Plugin size does not change. +// 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. void TestFullscreen::DidChangeView(const pp::Rect& position, const pp::Rect& clip) { if (normal_position_.IsEmpty()) @@ -195,8 +199,8 @@ void TestFullscreen::DidChangeView(const pp::Rect& position, saw_first_fullscreen_didchangeview = true; if (!screen_mode_.IsFullscreen()) FailFullscreenTest("DidChangeView1 is not in fullscreen"); - if (position.size() != normal_position_.size()) - FailFullscreenTest("DidChangeView1 has different plugin size"); + if (position.size() != screen_size_) + FailFullscreenTest("DidChangeView1 does not have screen size"); // Wait for the 2nd DidChangeView. } else if (fullscreen_pending_) { fullscreen_pending_ = false; @@ -205,8 +209,10 @@ void TestFullscreen::DidChangeView(const pp::Rect& position, FailFullscreenTest("DidChangeView2 is not in fullscreen"); else if (!HasMidScreen(position, screen_size_)) FailFullscreenTest("DidChangeView2 is not in the middle of the screen"); - else if (position.size() != normal_position_.size()) - FailFullscreenTest("DidChangeView2 has different plugin size"); + else if (position.size() != screen_size_) + FailFullscreenTest("DidChangeView2 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 pp::Module::Get()->core()->CallOnMainThread(0, fullscreen_callback_); } else if (normal_pending_) { diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.cc b/webkit/plugins/ppapi/ppapi_plugin_instance.cc index 746b899..d13690b 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.cc +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.cc @@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "base/metrics/histogram.h" +#include "base/stringprintf.h" #include "base/utf_offset_string_conversions.h" #include "base/utf_string_conversions.h" #include "ppapi/c/dev/ppb_console_dev.h" @@ -99,6 +100,7 @@ #include "skia/ext/skia_utils_mac.h" #endif +using base::StringPrintf; using ppapi::InputEventImpl; using ppapi::StringVar; using ppapi::thunk::EnterResourceNoLock; @@ -115,6 +117,7 @@ using WebKit::WebConsoleMessage; using WebKit::WebCursorInfo; using WebKit::WebDocument; using WebKit::WebFrame; +using WebKit::WebElement; using WebKit::WebInputEvent; using WebKit::WebPluginContainer; using WebKit::WebString; @@ -165,6 +168,12 @@ const ui::TextInputType kPluginDefaultTextInputType = ui::TEXT_INPUT_TYPE_NONE; == static_cast<int>(np_name), \ mismatching_enums) +// <embed>/<object> attributes. +static const char kWidth[] = "width"; +static const char kHeight[] = "height"; +static const char kBorder[] = "border"; // According to w3c, deprecated. +static const char kStyle[] = "style"; + COMPILE_ASSERT_MATCHING_ENUM(TypePointer, PP_CURSORTYPE_POINTER); COMPILE_ASSERT_MATCHING_ENUM(TypeCross, PP_CURSORTYPE_CROSS); COMPILE_ASSERT_MATCHING_ENUM(TypeHand, PP_CURSORTYPE_HAND); @@ -237,7 +246,7 @@ bool SecurityOriginForInstance(PP_Instance instance_id, if (!instance) return false; - WebKit::WebElement plugin_element = instance->container()->element(); + WebElement plugin_element = instance->container()->element(); *security_origin = plugin_element.document().securityOrigin(); return true; } @@ -736,10 +745,29 @@ void PluginInstance::ViewChanged(const gfx::Rect& position, if (sent_did_change_view_ && position == position_ && new_clip == clip_) return; - sent_did_change_view_ = true; - position_ = position; - clip_ = new_clip; - fullscreen_ = desired_fullscreen_state_; + // TODO(polina): fullscreen transition might take multiple ViewChanged, + // so this will update the state too early. Also, when F11 is used to + // exit fullscreen mode, desired_fullscreen_state_ is not properly set + // and cannot be relied on. + // Pending fix: http://codereview.chromium.org/8273029/ + // WebKit: https://bugs.webkit.org/show_bug.cgi?id=70076. + if (desired_fullscreen_state_ && !fullscreen_) { + // Entered fullscreen. Only possible via SetFullscreen. + fullscreen_ = true; + } else if (!desired_fullscreen_state_ && fullscreen_) { + // Exited fullscreen. Possible via SetFullscreen or F11/link. + fullscreen_ = false; + // Reset the size attributes that we hacked to fill in the screen and + // retrigger ViewChanged. Make sure we don't forward duplicates of + // this view to the plugin. + ResetSizeAttributesAfterFullscreen(); + SetSentDidChangeView(position, new_clip); + MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(&PluginInstance::ReportGeometry, this)); + return; + } + + SetSentDidChangeView(position, new_clip); flash_fullscreen_ = (fullscreen_container_ != NULL); PP_Rect pp_position, pp_clip; @@ -1164,10 +1192,16 @@ bool PluginInstance::SetFullscreen(bool fullscreen, bool delay_report) { VLOG(1) << "Setting fullscreen to " << (fullscreen ? "on" : "off"); desired_fullscreen_state_ = fullscreen; - if (fullscreen) + + if (fullscreen) { + // WebKit does not resize the plugin to fill the screen in fullscreen mode, + // so we will tweak plugin's attributes to support the expected behavior. + KeepSizeAttributesBeforeFullscreen(); + SetSizeAttributesForFullscreen(); container_->element().requestFullScreen(); - else + } else { container_->element().document().cancelFullScreen(); + } if (!delay_report) { ReportGeometry(); } else { @@ -1901,7 +1935,7 @@ PP_Var PluginInstance::ResolveRelativeToDocument( if (!relative_string) return PP_MakeNull(); - WebKit::WebElement plugin_element = container()->element(); + WebElement plugin_element = container()->element(); GURL document_url = plugin_element.document().baseURL(); return ::ppapi::URLUtilImpl::GenerateURLReturn( module()->pp_module(), @@ -1978,5 +2012,54 @@ bool PluginInstance::CanAccessMainFrame() const { main_document.securityOrigin()); } +void PluginInstance::SetSentDidChangeView(const gfx::Rect& position, + const gfx::Rect& clip) { + sent_did_change_view_ = true; + position_ = position; + clip_ = clip; +} + +void PluginInstance::KeepSizeAttributesBeforeFullscreen() { + WebElement element = container_->element(); + width_before_fullscreen_ = element.getAttribute(WebString::fromUTF8(kWidth)); + height_before_fullscreen_ = + element.getAttribute(WebString::fromUTF8(kHeight)); + border_before_fullscreen_ = + element.getAttribute(WebString::fromUTF8(kBorder)); + style_before_fullscreen_ = element.getAttribute(WebString::fromUTF8(kStyle)); +} + +void PluginInstance::SetSizeAttributesForFullscreen() { + screen_size_for_fullscreen_ = delegate()->GetScreenSize(); + std::string width = StringPrintf("%d", screen_size_for_fullscreen_.width()); + std::string height = StringPrintf("%d", screen_size_for_fullscreen_.height()); + + WebElement element = container_->element(); + element.setAttribute(WebString::fromUTF8(kWidth), WebString::fromUTF8(width)); + element.setAttribute(WebString::fromUTF8(kHeight), + WebString::fromUTF8(height)); + element.setAttribute(WebString::fromUTF8(kBorder), WebString::fromUTF8("0")); + + // There should be no style settings that matter in fullscreen mode, + // so just replace them instead of appending. + // NOTE: "position: fixed" and "display: block" reset the plugin and + // using %% settings might not work without them (e.g. if the plugin is a + // child of a container element). + std::string style; + style += StringPrintf("width: %s !important; ", width.c_str()); + style += StringPrintf("height: %s !important; ", height.c_str()); + style += "margin: 0 !important; padding: 0 !important; border: 0 !important"; + container_->element().setAttribute(kStyle, WebString::fromUTF8(style)); +} + +void PluginInstance::ResetSizeAttributesAfterFullscreen() { + screen_size_for_fullscreen_ = gfx::Size(); + WebElement element = container_->element(); + element.setAttribute(WebString::fromUTF8(kWidth), width_before_fullscreen_); + element.setAttribute(WebString::fromUTF8(kHeight), height_before_fullscreen_); + element.setAttribute(WebString::fromUTF8(kBorder), border_before_fullscreen_); + element.setAttribute(WebString::fromUTF8(kStyle), style_before_fullscreen_); +} + } // namespace ppapi } // namespace webkit diff --git a/webkit/plugins/ppapi/ppapi_plugin_instance.h b/webkit/plugins/ppapi/ppapi_plugin_instance.h index 00fbfab..78c9ecd 100644 --- a/webkit/plugins/ppapi/ppapi_plugin_instance.h +++ b/webkit/plugins/ppapi/ppapi_plugin_instance.h @@ -32,6 +32,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCanvas.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" #include "ui/base/ime/text_input_type.h" #include "ui/gfx/rect.h" #include "webkit/plugins/ppapi/plugin_delegate.h" @@ -450,6 +451,15 @@ class PluginInstance : public base::RefCounted<PluginInstance>, // compositing path. bool IsViewAccelerated(); + // Remember view parameters that were sent to the plugin. + void SetSentDidChangeView(const gfx::Rect& position, const gfx::Rect& clip); + + // Track, set and reset size attributes to control the size of the plugin + // in and out of fullscreen mode. + void KeepSizeAttributesBeforeFullscreen(); + void SetSizeAttributesForFullscreen(); + void ResetSizeAttributesAfterFullscreen(); + PluginDelegate* delegate_; scoped_refptr<PluginModule> module_; scoped_ptr< ::ppapi::PPP_Instance_Combined> instance_interface_; @@ -570,6 +580,15 @@ class PluginInstance : public base::RefCounted<PluginInstance>, // It reflects the previous state when in transition. bool fullscreen_; + // WebKit does not resize the plugin when going into fullscreen mode, so we do + // this here by modifying the various plugin attributes and then restoring + // them on exit. + WebKit::WebString width_before_fullscreen_; + WebKit::WebString height_before_fullscreen_; + WebKit::WebString border_before_fullscreen_; + WebKit::WebString style_before_fullscreen_; + gfx::Size screen_size_for_fullscreen_; + // The MessageChannel used to implement bidirectional postMessage for the // instance. scoped_ptr<MessageChannel> message_channel_; |