Index: ui/views/controls/webview/webview.cc |
=================================================================== |
--- ui/views/controls/webview/webview.cc (revision 132579) |
+++ ui/views/controls/webview/webview.cc (working copy) |
@@ -5,8 +5,17 @@ |
#include "ui/views/controls/webview/webview.h" |
#include "content/public/browser/browser_context.h" |
+#include "content/public/browser/notification_details.h" |
+#include "content/public/browser/notification_registrar.h" |
+#include "content/public/browser/notification_source.h" |
+#include "content/public/browser/notification_types.h" |
+#include "content/public/browser/render_view_host.h" |
+#include "content/public/browser/render_widget_host_view.h" |
#include "ipc/ipc_message.h" |
+#include "ui/base/accessibility/accessible_view_state.h" |
+#include "ui/base/accessibility/accessibility_types.h" |
#include "ui/views/controls/native/native_view_host.h" |
+#include "ui/views/focus/focus_manager.h" |
namespace views { |
@@ -15,23 +24,47 @@ |
WebView::WebView(content::BrowserContext* browser_context) |
: wcv_holder_(new NativeViewHost), |
+ web_contents_(NULL), |
browser_context_(browser_context) { |
- Init(); |
+ AddChildView(wcv_holder_); |
} |
WebView::~WebView() { |
} |
-//////////////////////////////////////////////////////////////////////////////// |
-// WebView, private: |
+content::WebContents* WebView::GetWebContents() { |
+ if (!web_contents_) { |
+ wc_owner_.reset(content::WebContents::Create(browser_context_, |
+ NULL, |
+ MSG_ROUTING_NONE, |
+ NULL, |
+ NULL)); |
+ web_contents_ = wc_owner_.get(); |
+ web_contents_->SetDelegate(this); |
+ AttachWebContents(); |
+ } |
+ return web_contents_; |
+} |
-void WebView::Init() { |
- AddChildView(wcv_holder_); |
- web_contents_.reset( |
- content::WebContents::Create(browser_context_, NULL, MSG_ROUTING_NONE, |
- NULL, NULL)); |
+void WebView::SetWebContents(content::WebContents* web_contents) { |
+ if (web_contents == web_contents_) |
+ return; |
+ DetachWebContents(); |
+ wc_owner_.reset(); |
+ web_contents_ = web_contents; |
+ AttachWebContents(); |
} |
+void WebView::SetFastResize(bool fast_resize) { |
+ wcv_holder_->set_fast_resize(fast_resize); |
+} |
+ |
+void WebView::OnWebContentsFocused(content::WebContents* web_contents) { |
+ FocusManager* focus_manager = GetFocusManager(); |
+ if (focus_manager) |
+ focus_manager->SetFocusedView(this); |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// WebView, View overrides: |
@@ -40,8 +73,128 @@ |
} |
void WebView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { |
- if (is_add && child == this) |
+ if (is_add) |
+ AttachWebContents(); |
+} |
+ |
+bool WebView::SkipDefaultKeyEventProcessing(const views::KeyEvent& event) { |
+ // Don't look-up accelerators or tab-traversal if we are showing a non-crashed |
+ // TabContents. |
+ // We'll first give the page a chance to process the key events. If it does |
+ // not process them, they'll be returned to us and we'll treat them as |
+ // accelerators then. |
+ return web_contents_ && !web_contents_->IsCrashed(); |
+} |
+ |
+bool WebView::IsFocusable() const { |
+ // We need to be focusable when our contents is not a view hierarchy, as |
+ // clicking on the contents needs to focus us. |
+ return !!web_contents_; |
+} |
+ |
+void WebView::OnFocus() { |
+ if (web_contents_) |
+ web_contents_->Focus(); |
+} |
+ |
+void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
+ if (web_contents_) |
+ web_contents_->FocusThroughTabTraversal(reverse); |
+} |
+ |
+void WebView::GetAccessibleState(ui::AccessibleViewState* state) { |
+ state->role = ui::AccessibilityTypes::ROLE_GROUPING; |
+} |
+ |
+gfx::NativeViewAccessible WebView::GetNativeViewAccessible() { |
+ if (web_contents_) { |
+ content::RenderWidgetHostView* host_view = |
+ web_contents_->GetRenderWidgetHostView(); |
+ if (host_view) |
+ return host_view->GetNativeViewAccessible(); |
+ } |
+ return View::GetNativeViewAccessible(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// WebView, content::NotificationObserver implementation: |
+ |
+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); |
+ } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
+ WebContentsDestroyed(content::Source<content::WebContents>(source).ptr()); |
+ } else { |
+ NOTREACHED(); |
+ } |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// WebView, content::WebContentsDelegate implementation: |
+ |
+void WebView::WebContentsFocused(content::WebContents* web_contents) { |
+ DCHECK(wc_owner_.get()); |
+ // The WebView is only the delegate of WebContentses it creates itself. |
+ WebContentsFocused(web_contents_); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// 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_->GetNativeView()) { |
+ return; |
+ } |
+ |
+ if (web_contents_) { |
wcv_holder_->Attach(web_contents_->GetNativeView()); |
+ |
+ 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_)); |
+ } |
} |
+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 its been hidden. |
+ ShowWindow(web_contents_->GetNativeView(), SW_HIDE); |
+#endif |
+ } |
+ registrar_.RemoveAll(); |
+} |
+ |
+void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, |
+ content::RenderViewHost* new_host) { |
+ if (GetFocusManager()->GetFocusedView() == this) |
+ web_contents_->Focus(); |
+} |
+ |
+void WebView::WebContentsDestroyed(content::WebContents* web_contents) { |
+ DCHECK(web_contents == web_contents_); |
+ SetWebContents(NULL); |
+} |
+ |
} // namespace views |