Index: ui/views/controls/webview/webview.cc |
diff --git a/ui/views/controls/webview/webview.cc b/ui/views/controls/webview/webview.cc |
index 28b8b7adc21dff5546bf12d485e6e1b559b73f1d..a8b3a868186151ebb4be6a2e3dd0512dd69e2904 100644 |
--- a/ui/views/controls/webview/webview.cc |
+++ b/ui/views/controls/webview/webview.cc |
@@ -14,6 +14,7 @@ |
#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" |
#include "ipc/ipc_message.h" |
#include "ui/base/accessibility/accessibility_types.h" |
@@ -29,12 +30,38 @@ namespace views { |
// static |
const char WebView::kViewClassName[] = "WebView"; |
+class WebView::FullscreenObserver : public content::WebContentsObserver { |
sky
2013/09/10 19:38:58
Add a description.
Is there a particular reason y
miu
2013/09/11 03:57:03
Done, and also for its "cousin" in the Mac cocoa U
|
+ public: |
+ explicit FullscreenObserver(WebView* view) : view_(view) {} |
+ |
+ void Observe(content::WebContents* new_web_contents) { |
+ WebContentsObserver::Observe(new_web_contents); |
+ } |
+ |
+ virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE { |
+ view_->ReattachForFullscreenChange(true); |
+ } |
+ |
+ virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE { |
+ view_->ReattachForFullscreenChange(false); |
+ } |
+ |
+ private: |
+ WebView* const view_; |
sky
2013/09/10 19:38:58
members at the end of a section.
miu
2013/09/11 03:57:03
Done.
|
+ |
+ // 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 {} |
+}; |
sky
2013/09/10 19:38:58
DISALLOW...
miu
2013/09/11 03:57:03
Done.
|
+ |
//////////////////////////////////////////////////////////////////////////////// |
// WebView, public: |
WebView::WebView(content::BrowserContext* browser_context) |
: wcv_holder_(new NativeViewHost), |
web_contents_(NULL), |
+ is_embedding_fullscreen_widget_(false), |
browser_context_(browser_context), |
allow_accelerators_(false) { |
AddChildView(wcv_holder_); |
@@ -64,11 +91,34 @@ 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 (fullscreen_observer_) { |
+ fullscreen_observer_->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 (!fullscreen_observer_ && enable) { |
+ DCHECK(!is_embedding_fullscreen_widget_); |
+ fullscreen_observer_.reset(new FullscreenObserver(this)); |
+ fullscreen_observer_->Observe(web_contents_); |
+ should_be_embedded = |
+ web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
+ } else if (fullscreen_observer_ && !enable) { |
+ fullscreen_observer_.reset(); |
+ } |
+ 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 +176,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->GetRenderWidgetHost()->Focus(); |
+ } else { |
web_contents_->GetView()->Focus(); |
+ } |
} |
void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
@@ -186,63 +244,86 @@ void WebView::WebContentsFocused(content::WebContents* web_contents) { |
OnWebContentsFocused(web_contents_); |
} |
+bool WebView::EmbedsFullscreenWidget() const { |
+ DCHECK(wc_owner_.get()); |
+ return !!fullscreen_observer_; |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// 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()); |
+ 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 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) |
+ // 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* focus_manager = GetFocusManager(); |
+ if (focus_manager && focus_manager->GetFocusedView() == this) { |
+ if (is_embedding_fullscreen_widget_) |
+ web_contents_->GetFullscreenRenderWidgetHostView()->Focus(); |
+ else |
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_)); |
} |
+ 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::ReattachForFullscreenChange(bool enter_fullscreen) { |
+ DetachWebContents(); |
+ is_embedding_fullscreen_widget_ = enter_fullscreen && |
+ web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
+ AttachWebContents(); |
+} |
+ |
void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, |
content::RenderViewHost* new_host) { |
if (GetFocusManager()->GetFocusedView() == this) |