Chromium Code Reviews| 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) |