Chromium Code Reviews| 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_accessibility_state.h" | 7 #include "content/public/browser/browser_accessibility_state.h" |
| 8 #include "content/public/browser/browser_context.h" | 8 #include "content/public/browser/browser_context.h" |
| 9 #include "content/public/browser/navigation_controller.h" | 9 #include "content/public/browser/navigation_controller.h" |
| 10 #include "content/public/browser/notification_details.h" | 10 #include "content/public/browser/notification_details.h" |
| 11 #include "content/public/browser/notification_registrar.h" | 11 #include "content/public/browser/notification_registrar.h" |
| 12 #include "content/public/browser/notification_source.h" | 12 #include "content/public/browser/notification_source.h" |
| 13 #include "content/public/browser/notification_types.h" | 13 #include "content/public/browser/notification_types.h" |
| 14 #include "content/public/browser/render_view_host.h" | 14 #include "content/public/browser/render_view_host.h" |
| 15 #include "content/public/browser/render_widget_host_view.h" | 15 #include "content/public/browser/render_widget_host_view.h" |
| 16 #include "content/public/browser/web_contents.h" | 16 #include "content/public/browser/web_contents.h" |
| 17 #include "content/public/browser/web_contents_observer.h" | |
| 17 #include "content/public/browser/web_contents_view.h" | 18 #include "content/public/browser/web_contents_view.h" |
| 18 #include "ipc/ipc_message.h" | 19 #include "ipc/ipc_message.h" |
| 19 #include "ui/base/accessibility/accessibility_types.h" | 20 #include "ui/base/accessibility/accessibility_types.h" |
| 20 #include "ui/base/accessibility/accessible_view_state.h" | 21 #include "ui/base/accessibility/accessible_view_state.h" |
| 21 #include "ui/base/events/event.h" | 22 #include "ui/base/events/event.h" |
| 22 #include "ui/views/accessibility/native_view_accessibility.h" | 23 #include "ui/views/accessibility/native_view_accessibility.h" |
| 23 #include "ui/views/controls/native/native_view_host.h" | 24 #include "ui/views/controls/native/native_view_host.h" |
| 24 #include "ui/views/focus/focus_manager.h" | 25 #include "ui/views/focus/focus_manager.h" |
| 25 #include "ui/views/views_delegate.h" | 26 #include "ui/views/views_delegate.h" |
| 26 | 27 |
| 27 namespace views { | 28 namespace views { |
| 28 | 29 |
| 29 // static | 30 // static |
| 30 const char WebView::kViewClassName[] = "WebView"; | 31 const char WebView::kViewClassName[] = "WebView"; |
| 31 | 32 |
| 33 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
| |
| 34 public: | |
| 35 explicit FullscreenObserver(WebView* view) : view_(view) {} | |
| 36 | |
| 37 void Observe(content::WebContents* new_web_contents) { | |
| 38 WebContentsObserver::Observe(new_web_contents); | |
| 39 } | |
| 40 | |
| 41 virtual void DidShowFullscreenWidget(int routing_id) OVERRIDE { | |
| 42 view_->ReattachForFullscreenChange(true); | |
| 43 } | |
| 44 | |
| 45 virtual void DidDestroyFullscreenWidget(int routing_id) OVERRIDE { | |
| 46 view_->ReattachForFullscreenChange(false); | |
| 47 } | |
| 48 | |
| 49 private: | |
| 50 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.
| |
| 51 | |
| 52 // Workaround for MSVC++ linker bug/feature that requires | |
| 53 // instantiation of the inline IPC::Listener methods in all translation units. | |
| 54 virtual void OnChannelConnected(int32 peer_id) OVERRIDE {} | |
| 55 virtual void OnChannelError() OVERRIDE {} | |
| 56 }; | |
|
sky
2013/09/10 19:38:58
DISALLOW...
miu
2013/09/11 03:57:03
Done.
| |
| 57 | |
| 32 //////////////////////////////////////////////////////////////////////////////// | 58 //////////////////////////////////////////////////////////////////////////////// |
| 33 // WebView, public: | 59 // WebView, public: |
| 34 | 60 |
| 35 WebView::WebView(content::BrowserContext* browser_context) | 61 WebView::WebView(content::BrowserContext* browser_context) |
| 36 : wcv_holder_(new NativeViewHost), | 62 : wcv_holder_(new NativeViewHost), |
| 37 web_contents_(NULL), | 63 web_contents_(NULL), |
| 64 is_embedding_fullscreen_widget_(false), | |
| 38 browser_context_(browser_context), | 65 browser_context_(browser_context), |
| 39 allow_accelerators_(false) { | 66 allow_accelerators_(false) { |
| 40 AddChildView(wcv_holder_); | 67 AddChildView(wcv_holder_); |
| 41 NativeViewAccessibility::RegisterWebView(this); | 68 NativeViewAccessibility::RegisterWebView(this); |
| 42 } | 69 } |
| 43 | 70 |
| 44 WebView::~WebView() { | 71 WebView::~WebView() { |
| 45 NativeViewAccessibility::UnregisterWebView(this); | 72 NativeViewAccessibility::UnregisterWebView(this); |
| 46 } | 73 } |
| 47 | 74 |
| 48 content::WebContents* WebView::GetWebContents() { | 75 content::WebContents* WebView::GetWebContents() { |
| 49 CreateWebContentsWithSiteInstance(NULL); | 76 CreateWebContentsWithSiteInstance(NULL); |
| 50 return web_contents_; | 77 return web_contents_; |
| 51 } | 78 } |
| 52 | 79 |
| 53 void WebView::CreateWebContentsWithSiteInstance( | 80 void WebView::CreateWebContentsWithSiteInstance( |
| 54 content::SiteInstance* site_instance) { | 81 content::SiteInstance* site_instance) { |
| 55 if (!web_contents_) { | 82 if (!web_contents_) { |
| 56 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); | 83 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); |
| 57 web_contents_ = wc_owner_.get(); | 84 web_contents_ = wc_owner_.get(); |
| 58 web_contents_->SetDelegate(this); | 85 web_contents_->SetDelegate(this); |
| 59 AttachWebContents(); | 86 AttachWebContents(); |
| 60 } | 87 } |
| 61 } | 88 } |
| 62 | 89 |
| 63 void WebView::SetWebContents(content::WebContents* web_contents) { | 90 void WebView::SetWebContents(content::WebContents* web_contents) { |
| 64 if (web_contents == web_contents_) | 91 if (web_contents == web_contents_) |
| 65 return; | 92 return; |
| 66 DetachWebContents(); | 93 DetachWebContents(); |
| 67 wc_owner_.reset(); | 94 if (wc_owner_ != web_contents) |
| 95 wc_owner_.reset(); | |
| 68 web_contents_ = web_contents; | 96 web_contents_ = web_contents; |
| 97 if (fullscreen_observer_) { | |
| 98 fullscreen_observer_->Observe(web_contents_); | |
| 99 is_embedding_fullscreen_widget_ = | |
| 100 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); | |
| 101 } else { | |
| 102 is_embedding_fullscreen_widget_ = false; | |
| 103 } | |
| 69 AttachWebContents(); | 104 AttachWebContents(); |
| 70 } | 105 } |
| 71 | 106 |
| 107 void WebView::SetEmbedFullscreenWidgetMode(bool enable) { | |
| 108 bool should_be_embedded = enable; | |
| 109 if (!fullscreen_observer_ && enable) { | |
| 110 DCHECK(!is_embedding_fullscreen_widget_); | |
| 111 fullscreen_observer_.reset(new FullscreenObserver(this)); | |
| 112 fullscreen_observer_->Observe(web_contents_); | |
| 113 should_be_embedded = | |
| 114 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); | |
| 115 } else if (fullscreen_observer_ && !enable) { | |
| 116 fullscreen_observer_.reset(); | |
| 117 } | |
| 118 if (should_be_embedded != is_embedding_fullscreen_widget_) | |
| 119 ReattachForFullscreenChange(should_be_embedded); | |
| 120 } | |
| 121 | |
| 72 void WebView::LoadInitialURL(const GURL& url) { | 122 void WebView::LoadInitialURL(const GURL& url) { |
| 73 GetWebContents()->GetController().LoadURL( | 123 GetWebContents()->GetController().LoadURL( |
| 74 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, | 124 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| 75 std::string()); | 125 std::string()); |
| 76 } | 126 } |
| 77 | 127 |
| 78 void WebView::SetFastResize(bool fast_resize) { | 128 void WebView::SetFastResize(bool fast_resize) { |
| 79 wcv_holder_->set_fast_resize(fast_resize); | 129 wcv_holder_->set_fast_resize(fast_resize); |
| 80 } | 130 } |
| 81 | 131 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 119 return web_contents_ && !web_contents_->IsCrashed(); | 169 return web_contents_ && !web_contents_->IsCrashed(); |
| 120 } | 170 } |
| 121 | 171 |
| 122 bool WebView::IsFocusable() const { | 172 bool WebView::IsFocusable() const { |
| 123 // We need to be focusable when our contents is not a view hierarchy, as | 173 // We need to be focusable when our contents is not a view hierarchy, as |
| 124 // clicking on the contents needs to focus us. | 174 // clicking on the contents needs to focus us. |
| 125 return !!web_contents_; | 175 return !!web_contents_; |
| 126 } | 176 } |
| 127 | 177 |
| 128 void WebView::OnFocus() { | 178 void WebView::OnFocus() { |
| 129 if (web_contents_) | 179 if (!web_contents_) |
| 180 return; | |
| 181 if (is_embedding_fullscreen_widget_) { | |
| 182 content::RenderWidgetHostView* const current_fs_view = | |
| 183 web_contents_->GetFullscreenRenderWidgetHostView(); | |
| 184 if (current_fs_view) | |
| 185 current_fs_view->GetRenderWidgetHost()->Focus(); | |
| 186 } else { | |
| 130 web_contents_->GetView()->Focus(); | 187 web_contents_->GetView()->Focus(); |
| 188 } | |
| 131 } | 189 } |
| 132 | 190 |
| 133 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { | 191 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
| 134 if (web_contents_) | 192 if (web_contents_) |
| 135 web_contents_->FocusThroughTabTraversal(reverse); | 193 web_contents_->FocusThroughTabTraversal(reverse); |
| 136 } | 194 } |
| 137 | 195 |
| 138 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { | 196 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { |
| 139 state->role = ui::AccessibilityTypes::ROLE_GROUPING; | 197 state->role = ui::AccessibilityTypes::ROLE_GROUPING; |
| 140 } | 198 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 179 | 237 |
| 180 //////////////////////////////////////////////////////////////////////////////// | 238 //////////////////////////////////////////////////////////////////////////////// |
| 181 // WebView, content::WebContentsDelegate implementation: | 239 // WebView, content::WebContentsDelegate implementation: |
| 182 | 240 |
| 183 void WebView::WebContentsFocused(content::WebContents* web_contents) { | 241 void WebView::WebContentsFocused(content::WebContents* web_contents) { |
| 184 DCHECK(wc_owner_.get()); | 242 DCHECK(wc_owner_.get()); |
| 185 // The WebView is only the delegate of WebContentses it creates itself. | 243 // The WebView is only the delegate of WebContentses it creates itself. |
| 186 OnWebContentsFocused(web_contents_); | 244 OnWebContentsFocused(web_contents_); |
| 187 } | 245 } |
| 188 | 246 |
| 247 bool WebView::EmbedsFullscreenWidget() const { | |
| 248 DCHECK(wc_owner_.get()); | |
| 249 return !!fullscreen_observer_; | |
| 250 } | |
| 251 | |
| 189 //////////////////////////////////////////////////////////////////////////////// | 252 //////////////////////////////////////////////////////////////////////////////// |
| 190 // WebView, private: | 253 // WebView, private: |
| 191 | 254 |
| 192 void WebView::AttachWebContents() { | 255 void WebView::AttachWebContents() { |
| 193 // Prevents attachment if the WebView isn't already in a Widget, or it's | 256 // Prevents attachment if the WebView isn't already in a Widget, or it's |
| 194 // already attached. | 257 // already attached. |
| 195 if (!GetWidget() || !web_contents_ || | 258 if (!GetWidget() || !web_contents_) |
| 196 wcv_holder_->native_view() == web_contents_->GetView()->GetNativeView()) { | |
| 197 return; | 259 return; |
| 260 | |
| 261 const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ? | |
| 262 web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() : | |
| 263 web_contents_->GetView()->GetNativeView(); | |
| 264 if (wcv_holder_->native_view() == view_to_attach) | |
| 265 return; | |
| 266 wcv_holder_->Attach(view_to_attach); | |
| 267 | |
| 268 // The view will not be focused automatically when it is attached, so we need | |
| 269 // to pass on focus to it if the FocusManager thinks the view is focused. Note | |
| 270 // that not every Widget has a focus manager. | |
| 271 FocusManager* focus_manager = GetFocusManager(); | |
| 272 if (focus_manager && focus_manager->GetFocusedView() == this) { | |
| 273 if (is_embedding_fullscreen_widget_) | |
| 274 web_contents_->GetFullscreenRenderWidgetHostView()->Focus(); | |
| 275 else | |
| 276 web_contents_->GetView()->Focus(); | |
| 198 } | 277 } |
| 199 | 278 |
| 200 if (web_contents_) { | 279 registrar_.Add( |
| 201 wcv_holder_->Attach(web_contents_->GetView()->GetNativeView()); | 280 this, |
| 202 | 281 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, |
| 203 // The WebContentsView will not be focused automatically when it is | 282 content::Source<content::NavigationController>( |
| 204 // attached, so we need to pass on focus to it if the FocusManager thinks | 283 &web_contents_->GetController())); |
| 205 // the WebView is focused. Note that not every Widget has a focus manager. | 284 registrar_.Add( |
| 206 FocusManager* focus_manager = GetFocusManager(); | 285 this, |
| 207 if (focus_manager && focus_manager->GetFocusedView() == this) | 286 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 208 web_contents_->GetView()->Focus(); | 287 content::Source<content::WebContents>(web_contents_)); |
| 209 | |
| 210 registrar_.Add( | |
| 211 this, | |
| 212 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | |
| 213 content::Source<content::NavigationController>( | |
| 214 &web_contents_->GetController())); | |
| 215 registrar_.Add( | |
| 216 this, | |
| 217 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
| 218 content::Source<content::WebContents>(web_contents_)); | |
| 219 } | |
| 220 | 288 |
| 221 #if defined(OS_WIN) && defined(USE_AURA) | 289 #if defined(OS_WIN) && defined(USE_AURA) |
| 222 web_contents_->SetParentNativeViewAccessible( | 290 if (!is_embedding_fullscreen_widget_) { |
| 223 parent()->GetNativeViewAccessible()); | 291 web_contents_->SetParentNativeViewAccessible( |
| 292 parent()->GetNativeViewAccessible()); | |
| 293 } | |
| 224 #endif | 294 #endif |
| 225 } | 295 } |
| 226 | 296 |
| 227 void WebView::DetachWebContents() { | 297 void WebView::DetachWebContents() { |
| 228 if (web_contents_) { | 298 if (web_contents_) { |
| 229 wcv_holder_->Detach(); | 299 wcv_holder_->Detach(); |
| 230 #if defined(OS_WIN) && !defined(USE_AURA) | 300 #if defined(OS_WIN) |
| 231 // TODO(beng): This should either not be necessary, or be done implicitly by | 301 if (!is_embedding_fullscreen_widget_) { |
| 232 // NativeViewHostWin on Detach(). As it stands, this is needed so that the | 302 #if !defined(USE_AURA) |
| 233 // view of the detached contents knows to tell the renderer it's been | 303 // TODO(beng): This should either not be necessary, or be done implicitly |
| 234 // hidden. | 304 // by NativeViewHostWin on Detach(). As it stands, this is needed so that |
| 235 // | 305 // the of the detached contents knows to tell the renderer it's been |
| 236 // Moving this out of here would also mean we wouldn't be potentially | 306 // hidden. |
| 237 // calling member functions on a half-destroyed WebContents. | 307 // |
| 238 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); | 308 // Moving this out of here would also mean we wouldn't be potentially |
| 239 #elif defined(OS_WIN) && defined(USE_AURA) | 309 // calling member functions on a half-destroyed WebContents. |
| 240 web_contents_->SetParentNativeViewAccessible(NULL); | 310 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); |
| 311 #else | |
| 312 web_contents_->SetParentNativeViewAccessible(NULL); | |
| 313 #endif | |
| 314 } | |
| 241 #endif | 315 #endif |
| 242 } | 316 } |
| 243 registrar_.RemoveAll(); | 317 registrar_.RemoveAll(); |
| 244 } | 318 } |
| 245 | 319 |
| 320 void WebView::ReattachForFullscreenChange(bool enter_fullscreen) { | |
| 321 DetachWebContents(); | |
| 322 is_embedding_fullscreen_widget_ = enter_fullscreen && | |
| 323 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); | |
| 324 AttachWebContents(); | |
| 325 } | |
| 326 | |
| 246 void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, | 327 void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, |
| 247 content::RenderViewHost* new_host) { | 328 content::RenderViewHost* new_host) { |
| 248 if (GetFocusManager()->GetFocusedView() == this) | 329 if (GetFocusManager()->GetFocusedView() == this) |
| 249 web_contents_->GetView()->Focus(); | 330 web_contents_->GetView()->Focus(); |
| 250 } | 331 } |
| 251 | 332 |
| 252 void WebView::WebContentsDestroyed(content::WebContents* web_contents) { | 333 void WebView::WebContentsDestroyed(content::WebContents* web_contents) { |
| 253 DCHECK(web_contents == web_contents_); | 334 DCHECK(web_contents == web_contents_); |
| 254 SetWebContents(NULL); | 335 SetWebContents(NULL); |
| 255 } | 336 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 266 if (!contents) { | 347 if (!contents) { |
| 267 content::WebContents::CreateParams create_params( | 348 content::WebContents::CreateParams create_params( |
| 268 browser_context, site_instance); | 349 browser_context, site_instance); |
| 269 return content::WebContents::Create(create_params); | 350 return content::WebContents::Create(create_params); |
| 270 } | 351 } |
| 271 | 352 |
| 272 return contents; | 353 return contents; |
| 273 } | 354 } |
| 274 | 355 |
| 275 } // namespace views | 356 } // namespace views |
| OLD | NEW |