summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-17 22:26:49 +0000
committermiu@chromium.org <miu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-09-17 22:26:49 +0000
commit4aebbcaacaa246be99dc81b3b93bbfc64f8f5a26 (patch)
tree5008c43aec2bafcb8faed309a2ce48bdca43f3e0
parentcce4cf72c69d2a8e347af4263fd691e21631ab2f (diff)
downloadchromium_src-4aebbcaacaa246be99dc81b3b93bbfc64f8f5a26.zip
chromium_src-4aebbcaacaa246be99dc81b3b93bbfc64f8f5a26.tar.gz
chromium_src-4aebbcaacaa246be99dc81b3b93bbfc64f8f5a26.tar.bz2
Embed Flash Fullscreen widget within browser window.
This provides users with a single, consistent fullscreen-mode experience, with Flash fullscreen gaining the improved window/desktop management behaviors of HTML5 fullscreen. This is accomplished by: 1) Modifying the browser window to insert Flash fullscreen widgets into the view hierarchy in response to "did show" notifications from WebContentsImpl; 2) Toggling browser window expansion (and user balloon pop-ups) via FullscreenController, the existing mechanism already used for HTML5 and F11 fullscreen. Safety: This enhancement is disabled by default, requiring an --embed-flash-fullscreen command-line flag to be activated. Testing: Confirmed Flash fullscreen works both the old way (as a separate, raw fullscreen window) and the new way (embedded within the browser window). Tested all fullscreen transitions: in-and-out, between browser F11 mode and Flash fullscreen mode, using the keyboard vs. mouse, "ALT-Tab" by the user and other window/desktop management modes, exit from balloon pop-up vs. plugin, and so on. For Flash compatibility, used IPC logging on Aura and Mac builds to confirm IPC messaging to the renderer process is identical to the old way. Left to do: 1) GTK support. 2) Mouse-lock support. BUG=290403 Review URL: https://chromiumcodereview.appspot.com/23477051 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@223715 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/browser.cc13
-rw-r--r--chrome/browser/ui/browser.h1
-rw-r--r--chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h21
-rw-r--r--chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm76
-rw-r--r--chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm12
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller.cc54
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller.h38
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc29
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_test.cc4
-rw-r--r--chrome/browser/ui/fullscreen/fullscreen_controller_test.h1
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc3
-rw-r--r--chrome/common/chrome_switches.cc8
-rw-r--r--chrome/common/chrome_switches.h1
-rw-r--r--content/browser/renderer_host/render_view_host_impl.cc7
-rw-r--r--content/browser/web_contents/web_contents_impl.cc53
-rw-r--r--content/browser/web_contents/web_contents_impl.h2
-rw-r--r--content/public/browser/web_contents.h6
-rw-r--r--content/public/browser/web_contents_delegate.cc4
-rw-r--r--content/public/browser/web_contents_delegate.h6
-rw-r--r--ui/views/controls/webview/webview.cc163
-rw-r--r--ui/views/controls/webview/webview.h30
21 files changed, 417 insertions, 115 deletions
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index bcf41f2..34923d2 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1603,6 +1603,19 @@ void Browser::EnumerateDirectory(WebContents* web_contents,
FileSelectHelper::EnumerateDirectory(web_contents, request_id, path);
}
+bool Browser::EmbedsFullscreenWidget() const {
+#if defined(TOOLKIT_GTK)
+ // TODO(miu): On GTK, the balloon widget for Tab/HTML5 fullscreen needs to be
+ // fixed before we can implement embedded fullscreen widgets.
+ // http://crbug.com/286545
+ return false;
+#else
+ // TODO(miu): Make this feature switchable in about:flags?
+ return CommandLine::ForCurrentProcess()->
+ HasSwitch(switches::kEmbedFlashFullscreen);
+#endif
+}
+
void Browser::ToggleFullscreenModeForTab(WebContents* web_contents,
bool enter_fullscreen) {
fullscreen_controller_->ToggleFullscreenModeForTab(web_contents,
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index ffe9677..a148cfd 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -620,6 +620,7 @@ class Browser : public TabStripModelObserver,
virtual void EnumerateDirectory(content::WebContents* web_contents,
int request_id,
const base::FilePath& path) OVERRIDE;
+ virtual bool EmbedsFullscreenWidget() const OVERRIDE;
virtual void ToggleFullscreenModeForTab(content::WebContents* web_contents,
bool enter_fullscreen) OVERRIDE;
virtual bool IsFullscreenForTabOrPending(
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
index c9cab99..6f1ca5b 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h
@@ -7,6 +7,10 @@
#include <Cocoa/Cocoa.h>
+#include "base/memory/scoped_ptr.h"
+
+class FullscreenObserver;
+
namespace content {
class WebContents;
}
@@ -21,11 +25,20 @@ class WebContents;
@interface TabContentsController : NSViewController {
@private
content::WebContents* contents_; // weak
+ // When |fullscreenObserver_| not-NULL, TabContentsController monitors for
+ // and auto-embeds fullscreen widgets as a subview.
+ scoped_ptr<FullscreenObserver> fullscreenObserver_;
+ // Set to true while TabContentsController is embedding a fullscreen widget
+ // view as a subview instead of the normal WebContentsView render view.
+ BOOL isEmbeddingFullscreenWidget_;
}
@property(readonly, nonatomic) content::WebContents* webContents;
-// Create the contents of a tab represented by |contents|.
-- (id)initWithContents:(content::WebContents*)contents;
+// Create the contents of a tab represented by |contents|. When
+// |enableEmbeddedFullscreen| is true, the WebContents view will automatically
+// be swapped with a fullscreen render widget owned by the current WebContents.
+- (id)initWithContents:(content::WebContents*)contents
+ andAutoEmbedFullscreen:(BOOL)enableEmbeddedFullscreen;
// Call when the tab contents is about to be replaced with the currently
// selected tab contents to do not trigger unnecessary content relayout.
@@ -54,6 +67,10 @@ class WebContents;
// an entirely new tab contents object.
- (void)tabDidChange:(content::WebContents*)updatedContents;
+// Called to switch the container's subview to the WebContents-owned fullscreen
+// widget or back to WebContentsView's widget.
+- (void)toggleFullscreenWidget:(BOOL)enterFullscreen;
+
@end
#endif // CHROME_BROWSER_UI_COCOA_TAB_CONTENTS_TAB_CONTENTS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
index 2e48592..9c7e83d 100644
--- a/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
+++ b/chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.mm
@@ -11,16 +11,55 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_view.h"
using content::WebContents;
+using content::WebContentsObserver;
+
+// FullscreenObserver is used by TabContentsController to monitor for the
+// showing/destruction of fullscreen render widgets. When notified,
+// TabContentsController will alter its child view hierarchy to either embed a
+// fullscreen render widget view or restore the normal WebContentsView render
+// view. The embedded fullscreen render widget will fill the user's screen in
+// the case where TabContentsController's NSView is a subview of a browser
+// window that has been toggled into fullscreen mode (e.g., via
+// FullscreenController).
+class FullscreenObserver : public WebContentsObserver {
+ public:
+ explicit FullscreenObserver(TabContentsController* controller)
+ : controller_(controller) {}
+
+ void Observe(content::WebContents* new_web_contents) {
+ WebContentsObserver::Observe(new_web_contents);
+ }
+
+ virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE {
+ [controller_ toggleFullscreenWidget:YES];
+ }
+
+ virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE {
+ [controller_ toggleFullscreenWidget:NO];
+ }
+
+ private:
+ TabContentsController* const controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(FullscreenObserver);
+};
@implementation TabContentsController
@synthesize webContents = contents_;
-- (id)initWithContents:(WebContents*)contents {
+- (id)initWithContents:(WebContents*)contents
+ andAutoEmbedFullscreen:(BOOL)enableEmbeddedFullscreen {
if ((self = [super initWithNibName:nil bundle:nil])) {
contents_ = contents;
+ if (enableEmbeddedFullscreen) {
+ fullscreenObserver_.reset(new FullscreenObserver(self));
+ fullscreenObserver_->Observe(contents_);
+ }
+ isEmbeddingFullscreenWidget_ = NO;
}
return self;
}
@@ -40,10 +79,8 @@ using content::WebContents;
- (void)ensureContentsSizeDoesNotChange {
NSView* contentsContainer = [self view];
NSArray* subviews = [contentsContainer subviews];
- if ([subviews count] > 0) {
- [contents_->GetView()->GetNativeView()
- setAutoresizingMask:NSViewNotSizable];
- }
+ if ([subviews count] > 0)
+ [[subviews objectAtIndex:0] setAutoresizingMask:NSViewNotSizable];
}
// Call when the tab view is properly sized and the render widget host view
@@ -53,7 +90,16 @@ using content::WebContents;
return;
NSView* contentsContainer = [self view];
NSArray* subviews = [contentsContainer subviews];
- NSView* contentsNativeView = contents_->GetView()->GetNativeView();
+ NSView* contentsNativeView;
+ content::RenderWidgetHostView* const fullscreenView =
+ isEmbeddingFullscreenWidget_ ?
+ contents_->GetFullscreenRenderWidgetHostView() : NULL;
+ if (fullscreenView) {
+ contentsNativeView = fullscreenView->GetNativeView();
+ } else {
+ isEmbeddingFullscreenWidget_ = NO;
+ contentsNativeView = contents_->GetView()->GetNativeView();
+ }
[contentsNativeView setFrame:[contentsContainer frame]];
if ([subviews count] == 0) {
[contentsContainer addSubview:contentsNativeView];
@@ -66,11 +112,19 @@ using content::WebContents;
// The rendering path with overlapping views disabled causes bugs when
// transitioning between composited and non-composited mode.
// http://crbug.com/279472
- contents_->GetView()->SetAllowOverlappingViews(true);
+ if (!fullscreenView)
+ contents_->GetView()->SetAllowOverlappingViews(true);
}
- (void)changeWebContents:(WebContents*)newContents {
contents_ = newContents;
+ if (fullscreenObserver_) {
+ fullscreenObserver_->Observe(contents_);
+ isEmbeddingFullscreenWidget_ =
+ contents_ && contents_->GetFullscreenRenderWidgetHostView();
+ } else {
+ isEmbeddingFullscreenWidget_ = NO;
+ }
}
// Returns YES if the tab represented by this controller is the front-most.
@@ -114,9 +168,15 @@ using content::WebContents;
// the view may have, so avoid changing the view hierarchy unless
// the view is different.
if ([self webContents] != updatedContents) {
- contents_ = updatedContents;
+ [self changeWebContents:updatedContents];
[self ensureContentsVisible];
}
}
+- (void)toggleFullscreenWidget:(BOOL)enterFullscreen {
+ isEmbeddingFullscreenWidget_ = enterFullscreen &&
+ contents_ && contents_->GetFullscreenRenderWidgetHostView();
+ [self ensureContentsVisible];
+}
+
@end
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index be3e0b7..8c57621 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -1296,8 +1296,12 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
// Make a new tab. Load the contents of this tab from the nib and associate
// the new controller with |contents| so it can be looked up later.
+ const BOOL autoEmbedFullscreen =
+ implicit_cast<content::WebContentsDelegate*>(browser_)->
+ EmbedsFullscreenWidget();
base::scoped_nsobject<TabContentsController> contentsController(
- [[TabContentsController alloc] initWithContents:contents]);
+ [[TabContentsController alloc] initWithContents:contents
+ andAutoEmbedFullscreen:autoEmbedFullscreen]);
[tabContentsArray_ insertObject:contentsController atIndex:index];
// Make a new tab and add it to the strip. Keep track of its controller.
@@ -1410,8 +1414,12 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
// Simply create a new TabContentsController for |newContents| and place it
// into the array, replacing |oldContents|. An ActiveTabChanged notification
// will follow, at which point we will install the new view.
+ const BOOL autoEmbedFullscreen =
+ implicit_cast<content::WebContentsDelegate*>(browser_)->
+ EmbedsFullscreenWidget();
base::scoped_nsobject<TabContentsController> newController(
- [[TabContentsController alloc] initWithContents:newContents]);
+ [[TabContentsController alloc] initWithContents:newContents
+ andAutoEmbedFullscreen:autoEmbedFullscreen]);
// Bye bye, |oldController|.
[tabContentsArray_ replaceObjectAtIndex:index withObject:newController];
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller.cc b/chrome/browser/ui/fullscreen/fullscreen_controller.cc
index d275cfe..c08bb22 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller.cc
@@ -48,7 +48,8 @@ FullscreenController::FullscreenController(Browser* browser)
toggled_into_fullscreen_(false),
mouse_lock_tab_(NULL),
mouse_lock_state_(MOUSELOCK_NOT_REQUESTED),
- reentrant_window_state_change_call_check_(false) {
+ reentrant_window_state_change_call_check_(false),
+ is_privileged_fullscreen_for_testing_(false) {
DCHECK(window_);
DCHECK(profile_);
}
@@ -235,7 +236,8 @@ void FullscreenController::RequestToLockMouse(WebContents* web_contents,
case CONTENT_SETTING_ALLOW:
// If bubble already displaying buttons we must not lock the mouse yet,
// or it would prevent pressing those buttons. Instead, merge the request.
- if (fullscreen_bubble::ShowButtonsForType(bubble_type)) {
+ if (!IsPrivilegedFullscreenForTab() &&
+ fullscreen_bubble::ShowButtonsForType(bubble_type)) {
mouse_lock_state_ = MOUSELOCK_REQUESTED;
} else {
// Lock mouse.
@@ -511,9 +513,8 @@ void FullscreenController::NotifyTabOfExitIfNecessary() {
if (IsMouseLockRequested()) {
mouse_lock_tab_->GotResponseToLockMouseRequest(false);
NotifyMouseLockChange();
- } else if (mouse_lock_tab_->GetRenderViewHost() &&
- mouse_lock_tab_->GetRenderViewHost()->GetView()) {
- mouse_lock_tab_->GetRenderViewHost()->GetView()->UnlockMouse();
+ } else {
+ UnlockMouse();
}
SetMouseLockTab(NULL);
mouse_lock_state_ = MOUSELOCK_NOT_REQUESTED;
@@ -529,7 +530,6 @@ void FullscreenController::NotifyMouseLockChange() {
content::NotificationService::NoDetails());
}
-// TODO(koz): Change |for_tab| to an enum.
void FullscreenController::ToggleFullscreenModeInternal(
FullscreenInternalOption option) {
#if defined(OS_WIN)
@@ -644,20 +644,15 @@ void FullscreenController::UpdateFullscreenExitBubbleContent() {
FullscreenExitBubbleType bubble_type = GetFullscreenExitBubbleType();
// If bubble displays buttons, unlock mouse to allow pressing them.
- if (fullscreen_bubble::ShowButtonsForType(bubble_type) &&
- IsMouseLocked() &&
- mouse_lock_tab_ &&
- mouse_lock_tab_->GetRenderViewHost() &&
- mouse_lock_tab_->GetRenderViewHost()->GetView()) {
- mouse_lock_tab_->GetRenderViewHost()->GetView()->UnlockMouse();
- }
+ if (fullscreen_bubble::ShowButtonsForType(bubble_type) && IsMouseLocked())
+ UnlockMouse();
window_->UpdateFullscreenExitBubbleContent(url, bubble_type);
}
ContentSetting
FullscreenController::GetFullscreenSetting(const GURL& url) const {
- if (url.SchemeIsFile())
+ if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile())
return CONTENT_SETTING_ALLOW;
return profile_->GetHostContentSettingsMap()->GetContentSetting(url, url,
@@ -666,10 +661,39 @@ FullscreenController::GetFullscreenSetting(const GURL& url) const {
ContentSetting
FullscreenController::GetMouseLockSetting(const GURL& url) const {
- if (url.SchemeIsFile())
+ if (IsPrivilegedFullscreenForTab() || url.SchemeIsFile())
return CONTENT_SETTING_ALLOW;
HostContentSettingsMap* settings_map = profile_->GetHostContentSettingsMap();
return settings_map->GetContentSetting(url, url,
CONTENT_SETTINGS_TYPE_MOUSELOCK, std::string());
}
+
+bool FullscreenController::IsPrivilegedFullscreenForTab() const {
+ const bool embedded_widget_present =
+ fullscreened_tab_ &&
+ fullscreened_tab_->GetFullscreenRenderWidgetHostView() &&
+ implicit_cast<const content::WebContentsDelegate*>(browser_)->
+ EmbedsFullscreenWidget();
+ return embedded_widget_present || is_privileged_fullscreen_for_testing_;
+}
+
+void FullscreenController::SetPrivilegedFullscreenForTesting(
+ bool is_privileged) {
+ is_privileged_fullscreen_for_testing_ = is_privileged;
+}
+
+void FullscreenController::UnlockMouse() {
+ if (!mouse_lock_tab_)
+ return;
+ content::RenderWidgetHostView* mouse_lock_view =
+ (fullscreened_tab_ == mouse_lock_tab_ && IsPrivilegedFullscreenForTab()) ?
+ mouse_lock_tab_->GetFullscreenRenderWidgetHostView() : NULL;
+ if (!mouse_lock_view) {
+ RenderViewHost* const rvh = mouse_lock_tab_->GetRenderViewHost();
+ if (rvh)
+ mouse_lock_view = rvh->GetView();
+ }
+ if (mouse_lock_view)
+ mouse_lock_view->UnlockMouse();
+}
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller.h b/chrome/browser/ui/fullscreen/fullscreen_controller.h
index b7ff113..ae5e20f 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller.h
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller.h
@@ -22,14 +22,18 @@ class WebContents;
}
// There are two different kinds of fullscreen mode - "tab fullscreen" and
-// "browser fullscreen". "Tab fullscreen" refers to when a tab enters
-// fullscreen mode via the JS fullscreen API, and "browser fullscreen" refers
-// to the user putting the browser itself into fullscreen mode from the UI. The
-// difference is that tab fullscreen has implications for how the contents of
-// the tab render (eg: a video element may grow to consume the whole tab),
-// whereas browser fullscreen mode doesn't. Therefore if a user forces an exit
-// from tab fullscreen, we need to notify the tab so it can stop rendering in
-// its fullscreen mode.
+// "browser fullscreen". "Tab fullscreen" refers to a renderer-initiated
+// fullscreen mode (eg: from a Flash plugin or via the JS fullscreen API),
+// whereas "browser fullscreen" refers to the user putting the browser itself
+// into fullscreen mode from the UI. The difference is that tab fullscreen has
+// implications for how the contents of the tab render (eg: a video element may
+// grow to consume the whole tab), whereas browser fullscreen mode doesn't.
+// Therefore if a user forces an exit from tab fullscreen, we need to notify the
+// tab so it can stop rendering in its fullscreen mode.
+//
+// For Flash, FullscreenController will auto-accept all permission requests for
+// fullscreen and/or mouse lock, since the assumption is that the plugin handles
+// this for us.
// This class implements fullscreen and mouselock behaviour.
class FullscreenController : public content::NotificationObserver {
@@ -45,7 +49,7 @@ class FullscreenController : public content::NotificationObserver {
void ToggleFullscreenMode();
- // Tab/HTML Fullscreen ///////////////////////////////////////////////////////
+ // Tab/HTML/Flash Fullscreen /////////////////////////////////////////////////
// Returns true if fullscreen has been caused by a tab.
// The window may still be transitioning, and window_->IsFullscreen()
@@ -122,6 +126,8 @@ class FullscreenController : public content::NotificationObserver {
FullscreenExitBubbleType GetFullscreenExitBubbleType() const;
private:
+ friend class FullscreenControllerTest;
+
enum MouseLockState {
MOUSELOCK_NOT_REQUESTED,
// The page requests to lock the mouse and the user hasn't responded to the
@@ -165,11 +171,15 @@ class FullscreenController : public content::NotificationObserver {
ContentSetting GetFullscreenSetting(const GURL& url) const;
ContentSetting GetMouseLockSetting(const GURL& url) const;
+ bool IsPrivilegedFullscreenForTab() const;
+ void SetPrivilegedFullscreenForTesting(bool is_privileged);
+ void UnlockMouse();
+
base::WeakPtrFactory<FullscreenController> ptr_factory_;
- Browser* browser_;
- BrowserWindow* window_;
- Profile* profile_;
+ Browser* const browser_;
+ BrowserWindow* const window_;
+ Profile* const profile_;
// If there is currently a tab in fullscreen mode (entered via
// webkitRequestFullScreen), this is its WebContents.
@@ -209,6 +219,10 @@ class FullscreenController : public content::NotificationObserver {
// WindowFullscreenStateChanged do so.
bool reentrant_window_state_change_call_check_;
+ // Used in testing to confirm proper behavior for specific, privileged
+ // fullscreen cases.
+ bool is_privileged_fullscreen_for_testing_;
+
DISALLOW_COPY_AND_ASSIGN(FullscreenController);
};
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc
index 1ab6665..159686f 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_interactive_browsertest.cc
@@ -625,6 +625,35 @@ IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
ASSERT_FALSE(IsFullscreenPermissionRequested());
}
+// Tests mouse lock and fullscreen for the privileged fullscreen case (e.g.,
+// embedded flash fullscreen, since the Flash plugin handles user permissions
+// requests itself).
+IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
+ PrivilegedMouseLockAndFullscreen) {
+ ASSERT_TRUE(test_server()->Start());
+ ui_test_utils::NavigateToURL(browser(),
+ test_server()->GetURL(kFullscreenMouseLockHTML));
+
+ ASSERT_FALSE(IsFullscreenBubbleDisplayed());
+
+ SetPrivilegedFullscreen(true);
+
+ // Request to lock the mouse and enter fullscreen.
+ FullscreenNotificationObserver fullscreen_observer;
+ ASSERT_TRUE(ui_test_utils::SendKeyPressAndWait(
+ browser(), ui::VKEY_B, false, true, false, false,
+ chrome::NOTIFICATION_MOUSE_LOCK_CHANGED,
+ content::NotificationService::AllSources()));
+ fullscreen_observer.Wait();
+
+ // Confirm they are enabled and there is no prompt.
+ ASSERT_TRUE(IsFullscreenBubbleDisplayed());
+ ASSERT_FALSE(IsFullscreenPermissionRequested());
+ ASSERT_FALSE(IsMouseLockPermissionRequested());
+ ASSERT_TRUE(IsMouseLocked());
+ ASSERT_TRUE(IsFullscreenForTabOrPending());
+}
+
// Tests mouse lock can be exited and re-entered by an application silently
// with no UI distraction for users.
IN_PROC_BROWSER_TEST_F(FullscreenControllerInteractiveTest,
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc b/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc
index 09afc17..51f5f71 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_test.cc
@@ -98,3 +98,7 @@ void FullscreenControllerTest::Reload() {
observer.Wait();
}
+void FullscreenControllerTest::SetPrivilegedFullscreen(bool is_privileged) {
+ browser()->fullscreen_controller()->
+ SetPrivilegedFullscreenForTesting(is_privileged);
+}
diff --git a/chrome/browser/ui/fullscreen/fullscreen_controller_test.h b/chrome/browser/ui/fullscreen/fullscreen_controller_test.h
index 94c3e2b..cb7d229 100644
--- a/chrome/browser/ui/fullscreen/fullscreen_controller_test.h
+++ b/chrome/browser/ui/fullscreen/fullscreen_controller_test.h
@@ -53,6 +53,7 @@ class FullscreenControllerTest : public InProcessBrowserTest {
void DenyCurrentFullscreenOrMouseLockRequest();
void GoBack();
void Reload();
+ void SetPrivilegedFullscreen(bool is_privileged);
static const char kFullscreenMouseLockHTML[];
private:
void ToggleTabFullscreen_Internal(bool enter_fullscreen,
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 7104bd1..bbd7822 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1943,6 +1943,9 @@ void BrowserView::InitViews() {
contents_web_view_ = new views::WebView(browser_->profile());
contents_web_view_->set_id(VIEW_ID_TAB_CONTAINER);
+ contents_web_view_->SetEmbedFullscreenWidgetMode(
+ implicit_cast<content::WebContentsDelegate*>(browser_.get())->
+ EmbedsFullscreenWidget());
contents_container_ = new ContentsContainer(contents_web_view_);
SkColor bg_color = GetWidget()->GetThemeProvider()->
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 4500f75..5472682 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -514,6 +514,14 @@ const char kDnsLogDetails[] = "dns-log-details";
// Disables prefetching of DNS information.
const char kDnsPrefetchDisable[] = "dns-prefetch-disable";
+// If set, Flash fullscreen widgets are embedded within the browser window and
+// with the same UX as HTML5 fullscreen.
+//
+// TODO(miu): This feature is a work in-progress. It should not be enabled by
+// default until going through a formal UX review, and all comments/concerns on
+// the crbug are addressed. http://crbug.com/290403
+const char kEmbedFlashFullscreen[] = "embed-flash-fullscreen";
+
// Enables the <adview> tag in packaged apps.
const char kEnableAdview[] = "enable-adview";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index fdb0d91..9fc85a3 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -156,6 +156,7 @@ extern const char kDiskCacheSize[];
extern const char kDnsLogDetails[];
extern const char kDnsPrefetchDisable[];
extern const char kEasyOffStoreExtensionInstall[];
+extern const char kEmbedFlashFullscreen[];
extern const char kEnableAdview[];
extern const char kEnableAdviewSrcAttribute[];
extern const char kEnableAppList[];
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index f260584..e18b754 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -1363,6 +1363,8 @@ void RenderViewHostImpl::OnContextMenu(const ContextMenuParams& params) {
void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
delegate_->ToggleFullscreenMode(enter_fullscreen);
+ // We need to notify the contents that its fullscreen state has changed. This
+ // is done as part of the resize message.
WasResized();
}
@@ -1782,9 +1784,8 @@ void RenderViewHostImpl::SetAltErrorPageURL(const GURL& url) {
void RenderViewHostImpl::ExitFullscreen() {
RejectMouseLockOrUnlockIfNecessary();
- // We need to notify the contents that its fullscreen state has changed. This
- // is done as part of the resize message.
- WasResized();
+ // Notify delegate_ and renderer of fullscreen state change.
+ OnToggleFullscreen(false);
}
WebPreferences RenderViewHostImpl::GetWebkitPreferences() {
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 16812f5..d6539b5 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -848,6 +848,14 @@ RenderWidgetHostViewPort* WebContentsImpl::GetRenderWidgetHostViewPort() const {
return RenderWidgetHostViewPort::FromRWHV(GetRenderWidgetHostView());
}
+RenderWidgetHostView* WebContentsImpl::GetFullscreenRenderWidgetHostView()
+ const {
+ RenderWidgetHost* const widget_host =
+ RenderWidgetHostImpl::FromID(GetRenderProcessHost()->GetID(),
+ GetFullscreenWidgetRoutingID());
+ return widget_host ? widget_host->GetView() : NULL;
+}
+
WebContentsView* WebContentsImpl::GetView() const {
return view_.get();
}
@@ -1330,6 +1338,8 @@ void WebContentsImpl::RenderWidgetDeleted(
if (render_widget_host &&
render_widget_host->GetRoutingID() == fullscreen_widget_routing_id_) {
+ if (delegate_ && delegate_->EmbedsFullscreenWidget())
+ delegate_->ToggleFullscreenModeForTab(this, false);
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
DidDestroyFullscreenWidget(
@@ -1407,6 +1417,13 @@ void WebContentsImpl::HandleGestureEnd() {
}
void WebContentsImpl::ToggleFullscreenMode(bool enter_fullscreen) {
+ // This method is being called to enter or leave renderer-initiated fullscreen
+ // mode. Either way, make sure any existing fullscreen widget is shut down
+ // first.
+ RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
+ if (widget_view)
+ RenderWidgetHostImpl::From(widget_view->GetRenderWidgetHost())->Shutdown();
+
if (delegate_)
delegate_->ToggleFullscreenModeForTab(this, enter_fullscreen);
}
@@ -1603,12 +1620,6 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
void WebContentsImpl::ShowCreatedFullscreenWidget(int route_id) {
ShowCreatedWidget(route_id, true, gfx::Rect());
-
- DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
- fullscreen_widget_routing_id_ = route_id;
- FOR_EACH_OBSERVER(WebContentsObserver,
- observers_,
- DidShowFullscreenWidget(route_id));
}
void WebContentsImpl::ShowCreatedWidget(int route_id,
@@ -1621,17 +1632,35 @@ void WebContentsImpl::ShowCreatedWidget(int route_id,
RenderWidgetHostViewPort::FromRWHV(GetCreatedWidget(route_id));
if (!widget_host_view)
return;
- if (is_fullscreen)
- widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort());
- else
+ bool allow_privileged = false;
+ if (is_fullscreen) {
+ if (delegate_ && delegate_->EmbedsFullscreenWidget()) {
+ widget_host_view->InitAsChild(GetRenderWidgetHostView()->GetNativeView());
+ delegate_->ToggleFullscreenModeForTab(this, true);
+ } else {
+ widget_host_view->InitAsFullscreen(GetRenderWidgetHostViewPort());
+ // Only allow privileged mouse lock for fullscreen render widget, which is
+ // used to implement Pepper Flash fullscreen.
+ allow_privileged = true;
+ }
+
+ DCHECK_EQ(MSG_ROUTING_NONE, fullscreen_widget_routing_id_);
+ fullscreen_widget_routing_id_ = route_id;
+ FOR_EACH_OBSERVER(WebContentsObserver,
+ observers_,
+ DidShowFullscreenWidget(route_id));
+ if (!widget_host_view->HasFocus())
+ widget_host_view->Focus();
+ } else {
widget_host_view->InitAsPopup(GetRenderWidgetHostViewPort(), initial_pos);
+ }
RenderWidgetHostImpl* render_widget_host_impl =
RenderWidgetHostImpl::From(widget_host_view->GetRenderWidgetHost());
render_widget_host_impl->Init();
- // Only allow privileged mouse lock for fullscreen render widget, which is
- // used to implement Pepper Flash fullscreen.
- render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen);
+ render_widget_host_impl->set_allow_privileged_mouse_lock(allow_privileged);
+ // TODO(miu): For now, all mouse lock requests by embedded Flash fullscreen
+ // will be denied. This is to be rectified in a soon-upcoming change.
#if defined(OS_MACOSX)
// A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 459ab30..4172e8a 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -223,6 +223,8 @@ class CONTENT_EXPORT WebContentsImpl
virtual int GetEmbeddedInstanceID() const OVERRIDE;
virtual int GetRoutingID() const OVERRIDE;
virtual RenderWidgetHostView* GetRenderWidgetHostView() const OVERRIDE;
+ virtual RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const
+ OVERRIDE;
virtual WebContentsView* GetView() const OVERRIDE;
virtual WebUI* CreateWebUI(const GURL& url) OVERRIDE;
virtual WebUI* GetWebUI() const OVERRIDE;
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index e1e6189..f753c16 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -196,7 +196,11 @@ class WebContents : public PageNavigator,
// Returns the currently active RenderWidgetHostView. This may change over
// time and can be NULL (during setup and teardown).
- virtual content::RenderWidgetHostView* GetRenderWidgetHostView() const = 0;
+ virtual RenderWidgetHostView* GetRenderWidgetHostView() const = 0;
+
+ // Returns the currently active fullscreen widget. If there is none, returns
+ // NULL.
+ virtual RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const = 0;
// The WebContentsView will never change and is guaranteed non-NULL.
virtual WebContentsView* GetView() const = 0;
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 9621fa7..924cabb 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -136,6 +136,10 @@ JavaScriptDialogManager* WebContentsDelegate::GetJavaScriptDialogManager() {
return NULL;
}
+bool WebContentsDelegate::EmbedsFullscreenWidget() const {
+ return false;
+}
+
bool WebContentsDelegate::IsFullscreenForTabOrPending(
const WebContents* web_contents) const {
return false;
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index e31828b..f4a889c 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -348,6 +348,12 @@ class CONTENT_EXPORT WebContentsDelegate {
int request_id,
const base::FilePath& path) {}
+ // Returns true if the delegate will embed a WebContents-owned fullscreen
+ // render widget. In this case, the delegate may access the widget by calling
+ // WebContents::GetFullscreenRenderWidgetHostView(). If false is returned,
+ // WebContents will be responsible for showing the fullscreen widget.
+ virtual bool EmbedsFullscreenWidget() const;
+
// Called when the renderer puts a tab into or out of fullscreen mode.
virtual void ToggleFullscreenModeForTab(WebContents* web_contents,
bool enter_fullscreen) {}
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc
index 28b8b7a..15fed84 100644
--- a/ui/views/controls/webview/webview.cc
+++ b/ui/views/controls/webview/webview.cc
@@ -35,6 +35,8 @@ const char WebView::kViewClassName[] = "WebView";
WebView::WebView(content::BrowserContext* browser_context)
: wcv_holder_(new NativeViewHost),
web_contents_(NULL),
+ embed_fullscreen_widget_mode_enabled_(false),
+ is_embedding_fullscreen_widget_(false),
browser_context_(browser_context),
allow_accelerators_(false) {
AddChildView(wcv_holder_);
@@ -64,11 +66,35 @@ void WebView::SetWebContents(content::WebContents* web_contents) {
if (web_contents == web_contents_)
return;
DetachWebContents();
- wc_owner_.reset();
+ if (wc_owner_ != web_contents)
+ wc_owner_.reset();
web_contents_ = web_contents;
+ if (embed_fullscreen_widget_mode_enabled_) {
+ WebContentsObserver::Observe(web_contents_);
+ is_embedding_fullscreen_widget_ =
+ web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
+ } else {
+ is_embedding_fullscreen_widget_ = false;
+ }
AttachWebContents();
}
+void WebView::SetEmbedFullscreenWidgetMode(bool enable) {
+ bool should_be_embedded = enable;
+ if (!embed_fullscreen_widget_mode_enabled_ && enable) {
+ DCHECK(!is_embedding_fullscreen_widget_);
+ embed_fullscreen_widget_mode_enabled_ = true;
+ WebContentsObserver::Observe(web_contents_);
+ should_be_embedded =
+ web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
+ } else if (embed_fullscreen_widget_mode_enabled_ && !enable) {
+ embed_fullscreen_widget_mode_enabled_ = false;
+ WebContentsObserver::Observe(NULL);
+ }
+ if (should_be_embedded != is_embedding_fullscreen_widget_)
+ ReattachForFullscreenChange(should_be_embedded);
+}
+
void WebView::LoadInitialURL(const GURL& url) {
GetWebContents()->GetController().LoadURL(
url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL,
@@ -126,8 +152,16 @@ bool WebView::IsFocusable() const {
}
void WebView::OnFocus() {
- if (web_contents_)
+ if (!web_contents_)
+ return;
+ if (is_embedding_fullscreen_widget_) {
+ content::RenderWidgetHostView* const current_fs_view =
+ web_contents_->GetFullscreenRenderWidgetHostView();
+ if (current_fs_view)
+ current_fs_view->Focus();
+ } else {
web_contents_->GetView()->Focus();
+ }
}
void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) {
@@ -163,15 +197,13 @@ void WebView::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) {
- std::pair<content::RenderViewHost*, content::RenderViewHost*>*
- switched_details =
- content::Details<std::pair<content::RenderViewHost*,
- content::RenderViewHost*> >(
- details).ptr();
- RenderViewHostChanged(switched_details->first,
- switched_details->second);
+ FocusManager* const focus_manager = GetFocusManager();
+ if (focus_manager && focus_manager->GetFocusedView() == this)
+ OnFocus();
} else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
- WebContentsDestroyed(content::Source<content::WebContents>(source).ptr());
+ DCHECK(content::Source<content::WebContents>(source).ptr() ==
+ web_contents_);
+ SetWebContents(NULL);
} else {
NOTREACHED();
}
@@ -186,72 +218,93 @@ void WebView::WebContentsFocused(content::WebContents* web_contents) {
OnWebContentsFocused(web_contents_);
}
+bool WebView::EmbedsFullscreenWidget() const {
+ DCHECK(wc_owner_.get());
+ return embed_fullscreen_widget_mode_enabled_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WebView, content::WebContentsObserver implementation:
+
+void WebView::DidShowFullscreenWidget(int routing_id) {
+ DCHECK(embed_fullscreen_widget_mode_enabled_);
+ ReattachForFullscreenChange(true);
+}
+
+void WebView::DidDestroyFullscreenWidget(int routing_id) {
+ DCHECK(embed_fullscreen_widget_mode_enabled_);
+ ReattachForFullscreenChange(false);
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebView, private:
void WebView::AttachWebContents() {
// Prevents attachment if the WebView isn't already in a Widget, or it's
// already attached.
- if (!GetWidget() || !web_contents_ ||
- wcv_holder_->native_view() == web_contents_->GetView()->GetNativeView()) {
+ if (!GetWidget() || !web_contents_)
return;
- }
- if (web_contents_) {
- wcv_holder_->Attach(web_contents_->GetView()->GetNativeView());
-
- // The WebContentsView will not be focused automatically when it is
- // attached, so we need to pass on focus to it if the FocusManager thinks
- // the WebView is focused. Note that not every Widget has a focus manager.
- FocusManager* focus_manager = GetFocusManager();
- if (focus_manager && focus_manager->GetFocusedView() == this)
- web_contents_->GetView()->Focus();
-
- registrar_.Add(
- this,
- content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
- content::Source<content::NavigationController>(
- &web_contents_->GetController()));
- registrar_.Add(
- this,
- content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<content::WebContents>(web_contents_));
- }
+ const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ?
+ web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() :
+ web_contents_->GetView()->GetNativeView();
+ if (wcv_holder_->native_view() == view_to_attach)
+ return;
+ wcv_holder_->Attach(view_to_attach);
+
+ // The view will not be focused automatically when it is attached, so we need
+ // to pass on focus to it if the FocusManager thinks the view is focused. Note
+ // that not every Widget has a focus manager.
+ FocusManager* const focus_manager = GetFocusManager();
+ if (focus_manager && focus_manager->GetFocusedView() == this)
+ OnFocus();
+
+ registrar_.Add(
+ this,
+ content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
+ content::Source<content::NavigationController>(
+ &web_contents_->GetController()));
+ registrar_.Add(
+ this,
+ content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::Source<content::WebContents>(web_contents_));
#if defined(OS_WIN) && defined(USE_AURA)
- web_contents_->SetParentNativeViewAccessible(
- parent()->GetNativeViewAccessible());
+ if (!is_embedding_fullscreen_widget_) {
+ web_contents_->SetParentNativeViewAccessible(
+ parent()->GetNativeViewAccessible());
+ }
#endif
}
void WebView::DetachWebContents() {
if (web_contents_) {
wcv_holder_->Detach();
-#if defined(OS_WIN) && !defined(USE_AURA)
- // TODO(beng): This should either not be necessary, or be done implicitly by
- // NativeViewHostWin on Detach(). As it stands, this is needed so that the
- // view of the detached contents knows to tell the renderer it's been
- // hidden.
- //
- // Moving this out of here would also mean we wouldn't be potentially
- // calling member functions on a half-destroyed WebContents.
- ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE);
-#elif defined(OS_WIN) && defined(USE_AURA)
- web_contents_->SetParentNativeViewAccessible(NULL);
+#if defined(OS_WIN)
+ if (!is_embedding_fullscreen_widget_) {
+#if !defined(USE_AURA)
+ // TODO(beng): This should either not be necessary, or be done implicitly
+ // by NativeViewHostWin on Detach(). As it stands, this is needed so that
+ // the of the detached contents knows to tell the renderer it's been
+ // hidden.
+ //
+ // Moving this out of here would also mean we wouldn't be potentially
+ // calling member functions on a half-destroyed WebContents.
+ ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE);
+#else
+ web_contents_->SetParentNativeViewAccessible(NULL);
+#endif
+ }
#endif
}
registrar_.RemoveAll();
}
-void WebView::RenderViewHostChanged(content::RenderViewHost* old_host,
- content::RenderViewHost* new_host) {
- if (GetFocusManager()->GetFocusedView() == this)
- web_contents_->GetView()->Focus();
-}
-
-void WebView::WebContentsDestroyed(content::WebContents* web_contents) {
- DCHECK(web_contents == web_contents_);
- SetWebContents(NULL);
+void WebView::ReattachForFullscreenChange(bool enter_fullscreen) {
+ DetachWebContents();
+ is_embedding_fullscreen_widget_ = enter_fullscreen &&
+ web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView();
+ AttachWebContents();
}
content::WebContents* WebView::CreateWebContents(
diff --git a/ui/views/controls/webview/webview.h b/ui/views/controls/webview/webview.h
index 05c447d..7e50914 100644
--- a/ui/views/controls/webview/webview.h
+++ b/ui/views/controls/webview/webview.h
@@ -10,6 +10,7 @@
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
#include "ui/views/accessibility/native_view_accessibility.h"
#include "ui/views/controls/webview/webview_export.h"
#include "ui/views/view.h"
@@ -24,7 +25,8 @@ class NativeViewHost;
class WEBVIEW_EXPORT WebView : public View,
public content::NotificationObserver,
- public content::WebContentsDelegate {
+ public content::WebContentsDelegate,
+ public content::WebContentsObserver {
public:
static const char kViewClassName[];
@@ -43,6 +45,12 @@ class WEBVIEW_EXPORT WebView : public View,
// those it implicitly creates via GetWebContents() above.
void SetWebContents(content::WebContents* web_contents);
+ // If |mode| is true, WebView will register itself with WebContents as a
+ // WebContentsObserver, monitor for the showing/destruction of fullscreen
+ // render widgets, and alter its child view hierarchy to embed the fullscreen
+ // widget or restore the normal WebContentsView.
+ void SetEmbedFullscreenWidgetMode(bool mode);
+
content::WebContents* web_contents() { return web_contents_; }
content::BrowserContext* browser_context() { return browser_context_; }
@@ -103,13 +111,19 @@ class WEBVIEW_EXPORT WebView : public View,
// Overridden from content::WebContentsDelegate:
virtual void WebContentsFocused(content::WebContents* web_contents) OVERRIDE;
+ virtual bool EmbedsFullscreenWidget() const OVERRIDE;
+
+ // Overridden from content::WebContentsObserver:
+ virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE;
+ virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE;
+ // Workaround for MSVC++ linker bug/feature that requires
+ // instantiation of the inline IPC::Listener methods in all translation units.
+ virtual void OnChannelConnected(int32 peer_id) OVERRIDE {}
+ virtual void OnChannelError() OVERRIDE {}
void AttachWebContents();
void DetachWebContents();
-
- void RenderViewHostChanged(content::RenderViewHost* old_host,
- content::RenderViewHost* new_host);
- void WebContentsDestroyed(content::WebContents* web_contents);
+ void ReattachForFullscreenChange(bool enter_fullscreen);
// Create a regular or test web contents (based on whether we're running
// in a unit test or not).
@@ -120,6 +134,12 @@ class WEBVIEW_EXPORT WebView : public View,
NativeViewHost* wcv_holder_;
scoped_ptr<content::WebContents> wc_owner_;
content::WebContents* web_contents_;
+ // When true, WebView observes WebContents and auto-embeds fullscreen widgets
+ // as a child view.
+ bool embed_fullscreen_widget_mode_enabled_;
+ // Set to true while WebView is embedding a fullscreen widget view as a child
+ // view instead of the normal WebContentsView render view.
+ bool is_embedding_fullscreen_widget_;
content::BrowserContext* browser_context_;
content::NotificationRegistrar registrar_;
bool allow_accelerators_;