OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/views/controls/webview/webview.h" | 5 #include "ui/views/controls/webview/webview.h" |
6 | 6 |
7 #include "content/public/browser/browser_context.h" | 7 #include "content/public/browser/browser_context.h" |
| 8 #include "content/public/browser/notification_details.h" |
| 9 #include "content/public/browser/notification_registrar.h" |
| 10 #include "content/public/browser/notification_source.h" |
| 11 #include "content/public/browser/notification_types.h" |
| 12 #include "content/public/browser/render_view_host.h" |
| 13 #include "content/public/browser/render_widget_host_view.h" |
8 #include "ipc/ipc_message.h" | 14 #include "ipc/ipc_message.h" |
| 15 #include "ui/base/accessibility/accessible_view_state.h" |
| 16 #include "ui/base/accessibility/accessibility_types.h" |
9 #include "ui/views/controls/native/native_view_host.h" | 17 #include "ui/views/controls/native/native_view_host.h" |
| 18 #include "ui/views/focus/focus_manager.h" |
10 | 19 |
11 namespace views { | 20 namespace views { |
12 | 21 |
13 //////////////////////////////////////////////////////////////////////////////// | 22 //////////////////////////////////////////////////////////////////////////////// |
14 // WebView, public: | 23 // WebView, public: |
15 | 24 |
16 WebView::WebView(content::BrowserContext* browser_context) | 25 WebView::WebView(content::BrowserContext* browser_context) |
17 : wcv_holder_(new NativeViewHost), | 26 : wcv_holder_(new NativeViewHost), |
| 27 web_contents_(NULL), |
18 browser_context_(browser_context) { | 28 browser_context_(browser_context) { |
19 Init(); | 29 AddChildView(wcv_holder_); |
20 } | 30 } |
21 | 31 |
22 WebView::~WebView() { | 32 WebView::~WebView() { |
23 } | 33 } |
24 | 34 |
25 //////////////////////////////////////////////////////////////////////////////// | 35 content::WebContents* WebView::GetWebContents() { |
26 // WebView, private: | 36 if (!web_contents_) { |
| 37 wc_owner_.reset(content::WebContents::Create(browser_context_, |
| 38 NULL, |
| 39 MSG_ROUTING_NONE, |
| 40 NULL, |
| 41 NULL)); |
| 42 web_contents_ = wc_owner_.get(); |
| 43 web_contents_->SetDelegate(this); |
| 44 AttachWebContents(); |
| 45 } |
| 46 return web_contents_; |
| 47 } |
27 | 48 |
28 void WebView::Init() { | 49 void WebView::SetWebContents(content::WebContents* web_contents) { |
29 AddChildView(wcv_holder_); | 50 if (web_contents == web_contents_) |
30 web_contents_.reset( | 51 return; |
31 content::WebContents::Create(browser_context_, NULL, MSG_ROUTING_NONE, | 52 DetachWebContents(); |
32 NULL, NULL)); | 53 wc_owner_.reset(); |
| 54 web_contents_ = web_contents; |
| 55 AttachWebContents(); |
| 56 } |
| 57 |
| 58 void WebView::SetFastResize(bool fast_resize) { |
| 59 wcv_holder_->set_fast_resize(fast_resize); |
| 60 } |
| 61 |
| 62 void WebView::OnWebContentsFocused(content::WebContents* web_contents) { |
| 63 FocusManager* focus_manager = GetFocusManager(); |
| 64 if (focus_manager) |
| 65 focus_manager->SetFocusedView(this); |
33 } | 66 } |
34 | 67 |
35 //////////////////////////////////////////////////////////////////////////////// | 68 //////////////////////////////////////////////////////////////////////////////// |
36 // WebView, View overrides: | 69 // WebView, View overrides: |
37 | 70 |
38 void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) { | 71 void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) { |
39 wcv_holder_->SetSize(bounds().size()); | 72 wcv_holder_->SetSize(bounds().size()); |
40 } | 73 } |
41 | 74 |
42 void WebView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { | 75 void WebView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { |
43 if (is_add && child == this) | 76 if (is_add) |
| 77 AttachWebContents(); |
| 78 } |
| 79 |
| 80 bool WebView::SkipDefaultKeyEventProcessing(const views::KeyEvent& event) { |
| 81 // Don't look-up accelerators or tab-traversal if we are showing a non-crashed |
| 82 // TabContents. |
| 83 // We'll first give the page a chance to process the key events. If it does |
| 84 // not process them, they'll be returned to us and we'll treat them as |
| 85 // accelerators then. |
| 86 return web_contents_ && !web_contents_->IsCrashed(); |
| 87 } |
| 88 |
| 89 bool WebView::IsFocusable() const { |
| 90 // We need to be focusable when our contents is not a view hierarchy, as |
| 91 // clicking on the contents needs to focus us. |
| 92 return !!web_contents_; |
| 93 } |
| 94 |
| 95 void WebView::OnFocus() { |
| 96 if (web_contents_) |
| 97 web_contents_->Focus(); |
| 98 } |
| 99 |
| 100 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
| 101 if (web_contents_) |
| 102 web_contents_->FocusThroughTabTraversal(reverse); |
| 103 } |
| 104 |
| 105 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { |
| 106 state->role = ui::AccessibilityTypes::ROLE_GROUPING; |
| 107 } |
| 108 |
| 109 gfx::NativeViewAccessible WebView::GetNativeViewAccessible() { |
| 110 if (web_contents_) { |
| 111 content::RenderWidgetHostView* host_view = |
| 112 web_contents_->GetRenderWidgetHostView(); |
| 113 if (host_view) |
| 114 return host_view->GetNativeViewAccessible(); |
| 115 } |
| 116 return View::GetNativeViewAccessible(); |
| 117 } |
| 118 |
| 119 //////////////////////////////////////////////////////////////////////////////// |
| 120 // WebView, content::NotificationObserver implementation: |
| 121 |
| 122 void WebView::Observe(int type, |
| 123 const content::NotificationSource& source, |
| 124 const content::NotificationDetails& details) { |
| 125 if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) { |
| 126 std::pair<content::RenderViewHost*, content::RenderViewHost*>* |
| 127 switched_details = |
| 128 content::Details<std::pair<content::RenderViewHost*, |
| 129 content::RenderViewHost*> >( |
| 130 details).ptr(); |
| 131 RenderViewHostChanged(switched_details->first, |
| 132 switched_details->second); |
| 133 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
| 134 WebContentsDestroyed(content::Source<content::WebContents>(source).ptr()); |
| 135 } else { |
| 136 NOTREACHED(); |
| 137 } |
| 138 } |
| 139 |
| 140 //////////////////////////////////////////////////////////////////////////////// |
| 141 // WebView, content::WebContentsDelegate implementation: |
| 142 |
| 143 void WebView::WebContentsFocused(content::WebContents* web_contents) { |
| 144 DCHECK(wc_owner_.get()); |
| 145 // The WebView is only the delegate of WebContentses it creates itself. |
| 146 WebContentsFocused(web_contents_); |
| 147 } |
| 148 |
| 149 //////////////////////////////////////////////////////////////////////////////// |
| 150 // WebView, private: |
| 151 |
| 152 void WebView::AttachWebContents() { |
| 153 // Prevents attachment if the WebView isn't already in a Widget, or it's |
| 154 // already attached. |
| 155 if (!GetWidget() || !web_contents_ || |
| 156 wcv_holder_->native_view() == web_contents_->GetNativeView()) { |
| 157 return; |
| 158 } |
| 159 |
| 160 if (web_contents_) { |
44 wcv_holder_->Attach(web_contents_->GetNativeView()); | 161 wcv_holder_->Attach(web_contents_->GetNativeView()); |
| 162 |
| 163 registrar_.Add( |
| 164 this, |
| 165 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, |
| 166 content::Source<content::NavigationController>( |
| 167 &web_contents_->GetController())); |
| 168 registrar_.Add( |
| 169 this, |
| 170 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 171 content::Source<content::WebContents>(web_contents_)); |
| 172 } |
| 173 } |
| 174 |
| 175 void WebView::DetachWebContents() { |
| 176 if (web_contents_) { |
| 177 wcv_holder_->Detach(); |
| 178 #if defined(OS_WIN) && !defined(USE_AURA) |
| 179 // TODO(beng): This should either not be necessary, or be done implicitly by |
| 180 // NativeViewHostWin on Detach(). As it stands, this is needed |
| 181 // so that the view of the detached contents knows to tell the |
| 182 // renderer its been hidden. |
| 183 ShowWindow(web_contents_->GetNativeView(), SW_HIDE); |
| 184 #endif |
| 185 } |
| 186 registrar_.RemoveAll(); |
| 187 } |
| 188 |
| 189 void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, |
| 190 content::RenderViewHost* new_host) { |
| 191 if (GetFocusManager()->GetFocusedView() == this) |
| 192 web_contents_->Focus(); |
| 193 } |
| 194 |
| 195 void WebView::WebContentsDestroyed(content::WebContents* web_contents) { |
| 196 DCHECK(web_contents == web_contents_); |
| 197 SetWebContents(NULL); |
45 } | 198 } |
46 | 199 |
47 } // namespace views | 200 } // namespace views |
OLD | NEW |