diff options
-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_; |