| 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" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 | 28 |
| 29 // static | 29 // static |
| 30 const char WebView::kViewClassName[] = "WebView"; | 30 const char WebView::kViewClassName[] = "WebView"; |
| 31 | 31 |
| 32 //////////////////////////////////////////////////////////////////////////////// | 32 //////////////////////////////////////////////////////////////////////////////// |
| 33 // WebView, public: | 33 // WebView, public: |
| 34 | 34 |
| 35 WebView::WebView(content::BrowserContext* browser_context) | 35 WebView::WebView(content::BrowserContext* browser_context) |
| 36 : wcv_holder_(new NativeViewHost), | 36 : wcv_holder_(new NativeViewHost), |
| 37 web_contents_(NULL), | 37 web_contents_(NULL), |
| 38 embed_fullscreen_widget_mode_enabled_(false), |
| 39 is_embedding_fullscreen_widget_(false), |
| 38 browser_context_(browser_context), | 40 browser_context_(browser_context), |
| 39 allow_accelerators_(false) { | 41 allow_accelerators_(false) { |
| 40 AddChildView(wcv_holder_); | 42 AddChildView(wcv_holder_); |
| 41 NativeViewAccessibility::RegisterWebView(this); | 43 NativeViewAccessibility::RegisterWebView(this); |
| 42 } | 44 } |
| 43 | 45 |
| 44 WebView::~WebView() { | 46 WebView::~WebView() { |
| 45 NativeViewAccessibility::UnregisterWebView(this); | 47 NativeViewAccessibility::UnregisterWebView(this); |
| 46 } | 48 } |
| 47 | 49 |
| 48 content::WebContents* WebView::GetWebContents() { | 50 content::WebContents* WebView::GetWebContents() { |
| 49 CreateWebContentsWithSiteInstance(NULL); | 51 CreateWebContentsWithSiteInstance(NULL); |
| 50 return web_contents_; | 52 return web_contents_; |
| 51 } | 53 } |
| 52 | 54 |
| 53 void WebView::CreateWebContentsWithSiteInstance( | 55 void WebView::CreateWebContentsWithSiteInstance( |
| 54 content::SiteInstance* site_instance) { | 56 content::SiteInstance* site_instance) { |
| 55 if (!web_contents_) { | 57 if (!web_contents_) { |
| 56 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); | 58 wc_owner_.reset(CreateWebContents(browser_context_, site_instance)); |
| 57 web_contents_ = wc_owner_.get(); | 59 web_contents_ = wc_owner_.get(); |
| 58 web_contents_->SetDelegate(this); | 60 web_contents_->SetDelegate(this); |
| 59 AttachWebContents(); | 61 AttachWebContents(); |
| 60 } | 62 } |
| 61 } | 63 } |
| 62 | 64 |
| 63 void WebView::SetWebContents(content::WebContents* web_contents) { | 65 void WebView::SetWebContents(content::WebContents* web_contents) { |
| 64 if (web_contents == web_contents_) | 66 if (web_contents == web_contents_) |
| 65 return; | 67 return; |
| 66 DetachWebContents(); | 68 DetachWebContents(); |
| 67 wc_owner_.reset(); | 69 if (wc_owner_ != web_contents) |
| 70 wc_owner_.reset(); |
| 68 web_contents_ = web_contents; | 71 web_contents_ = web_contents; |
| 72 if (embed_fullscreen_widget_mode_enabled_) { |
| 73 WebContentsObserver::Observe(web_contents_); |
| 74 is_embedding_fullscreen_widget_ = |
| 75 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
| 76 } else { |
| 77 is_embedding_fullscreen_widget_ = false; |
| 78 } |
| 69 AttachWebContents(); | 79 AttachWebContents(); |
| 70 } | 80 } |
| 71 | 81 |
| 82 void WebView::SetEmbedFullscreenWidgetMode(bool enable) { |
| 83 bool should_be_embedded = enable; |
| 84 if (!embed_fullscreen_widget_mode_enabled_ && enable) { |
| 85 DCHECK(!is_embedding_fullscreen_widget_); |
| 86 embed_fullscreen_widget_mode_enabled_ = true; |
| 87 WebContentsObserver::Observe(web_contents_); |
| 88 should_be_embedded = |
| 89 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
| 90 } else if (embed_fullscreen_widget_mode_enabled_ && !enable) { |
| 91 embed_fullscreen_widget_mode_enabled_ = false; |
| 92 WebContentsObserver::Observe(NULL); |
| 93 } |
| 94 if (should_be_embedded != is_embedding_fullscreen_widget_) |
| 95 ReattachForFullscreenChange(should_be_embedded); |
| 96 } |
| 97 |
| 72 void WebView::LoadInitialURL(const GURL& url) { | 98 void WebView::LoadInitialURL(const GURL& url) { |
| 73 GetWebContents()->GetController().LoadURL( | 99 GetWebContents()->GetController().LoadURL( |
| 74 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, | 100 url, content::Referrer(), content::PAGE_TRANSITION_AUTO_TOPLEVEL, |
| 75 std::string()); | 101 std::string()); |
| 76 } | 102 } |
| 77 | 103 |
| 78 void WebView::SetFastResize(bool fast_resize) { | 104 void WebView::SetFastResize(bool fast_resize) { |
| 79 wcv_holder_->set_fast_resize(fast_resize); | 105 wcv_holder_->set_fast_resize(fast_resize); |
| 80 } | 106 } |
| 81 | 107 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 return web_contents_ && !web_contents_->IsCrashed(); | 145 return web_contents_ && !web_contents_->IsCrashed(); |
| 120 } | 146 } |
| 121 | 147 |
| 122 bool WebView::IsFocusable() const { | 148 bool WebView::IsFocusable() const { |
| 123 // We need to be focusable when our contents is not a view hierarchy, as | 149 // We need to be focusable when our contents is not a view hierarchy, as |
| 124 // clicking on the contents needs to focus us. | 150 // clicking on the contents needs to focus us. |
| 125 return !!web_contents_; | 151 return !!web_contents_; |
| 126 } | 152 } |
| 127 | 153 |
| 128 void WebView::OnFocus() { | 154 void WebView::OnFocus() { |
| 129 if (web_contents_) | 155 if (!web_contents_) |
| 156 return; |
| 157 if (is_embedding_fullscreen_widget_) { |
| 158 content::RenderWidgetHostView* const current_fs_view = |
| 159 web_contents_->GetFullscreenRenderWidgetHostView(); |
| 160 if (current_fs_view) |
| 161 current_fs_view->Focus(); |
| 162 } else { |
| 130 web_contents_->GetView()->Focus(); | 163 web_contents_->GetView()->Focus(); |
| 164 } |
| 131 } | 165 } |
| 132 | 166 |
| 133 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { | 167 void WebView::AboutToRequestFocusFromTabTraversal(bool reverse) { |
| 134 if (web_contents_) | 168 if (web_contents_) |
| 135 web_contents_->FocusThroughTabTraversal(reverse); | 169 web_contents_->FocusThroughTabTraversal(reverse); |
| 136 } | 170 } |
| 137 | 171 |
| 138 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { | 172 void WebView::GetAccessibleState(ui::AccessibleViewState* state) { |
| 139 state->role = ui::AccessibilityTypes::ROLE_GROUPING; | 173 state->role = ui::AccessibilityTypes::ROLE_GROUPING; |
| 140 } | 174 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 156 return preferred_size_; | 190 return preferred_size_; |
| 157 } | 191 } |
| 158 | 192 |
| 159 //////////////////////////////////////////////////////////////////////////////// | 193 //////////////////////////////////////////////////////////////////////////////// |
| 160 // WebView, content::NotificationObserver implementation: | 194 // WebView, content::NotificationObserver implementation: |
| 161 | 195 |
| 162 void WebView::Observe(int type, | 196 void WebView::Observe(int type, |
| 163 const content::NotificationSource& source, | 197 const content::NotificationSource& source, |
| 164 const content::NotificationDetails& details) { | 198 const content::NotificationDetails& details) { |
| 165 if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) { | 199 if (type == content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED) { |
| 166 std::pair<content::RenderViewHost*, content::RenderViewHost*>* | 200 FocusManager* const focus_manager = GetFocusManager(); |
| 167 switched_details = | 201 if (focus_manager && focus_manager->GetFocusedView() == this) |
| 168 content::Details<std::pair<content::RenderViewHost*, | 202 OnFocus(); |
| 169 content::RenderViewHost*> >( | |
| 170 details).ptr(); | |
| 171 RenderViewHostChanged(switched_details->first, | |
| 172 switched_details->second); | |
| 173 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { | 203 } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
| 174 WebContentsDestroyed(content::Source<content::WebContents>(source).ptr()); | 204 DCHECK(content::Source<content::WebContents>(source).ptr() == |
| 205 web_contents_); |
| 206 SetWebContents(NULL); |
| 175 } else { | 207 } else { |
| 176 NOTREACHED(); | 208 NOTREACHED(); |
| 177 } | 209 } |
| 178 } | 210 } |
| 179 | 211 |
| 180 //////////////////////////////////////////////////////////////////////////////// | 212 //////////////////////////////////////////////////////////////////////////////// |
| 181 // WebView, content::WebContentsDelegate implementation: | 213 // WebView, content::WebContentsDelegate implementation: |
| 182 | 214 |
| 183 void WebView::WebContentsFocused(content::WebContents* web_contents) { | 215 void WebView::WebContentsFocused(content::WebContents* web_contents) { |
| 184 DCHECK(wc_owner_.get()); | 216 DCHECK(wc_owner_.get()); |
| 185 // The WebView is only the delegate of WebContentses it creates itself. | 217 // The WebView is only the delegate of WebContentses it creates itself. |
| 186 OnWebContentsFocused(web_contents_); | 218 OnWebContentsFocused(web_contents_); |
| 187 } | 219 } |
| 188 | 220 |
| 221 bool WebView::EmbedsFullscreenWidget() const { |
| 222 DCHECK(wc_owner_.get()); |
| 223 return embed_fullscreen_widget_mode_enabled_; |
| 224 } |
| 225 |
| 226 //////////////////////////////////////////////////////////////////////////////// |
| 227 // WebView, content::WebContentsObserver implementation: |
| 228 |
| 229 void WebView::DidShowFullscreenWidget(int routing_id) { |
| 230 DCHECK(embed_fullscreen_widget_mode_enabled_); |
| 231 ReattachForFullscreenChange(true); |
| 232 } |
| 233 |
| 234 void WebView::DidDestroyFullscreenWidget(int routing_id) { |
| 235 DCHECK(embed_fullscreen_widget_mode_enabled_); |
| 236 ReattachForFullscreenChange(false); |
| 237 } |
| 238 |
| 189 //////////////////////////////////////////////////////////////////////////////// | 239 //////////////////////////////////////////////////////////////////////////////// |
| 190 // WebView, private: | 240 // WebView, private: |
| 191 | 241 |
| 192 void WebView::AttachWebContents() { | 242 void WebView::AttachWebContents() { |
| 193 // Prevents attachment if the WebView isn't already in a Widget, or it's | 243 // Prevents attachment if the WebView isn't already in a Widget, or it's |
| 194 // already attached. | 244 // already attached. |
| 195 if (!GetWidget() || !web_contents_ || | 245 if (!GetWidget() || !web_contents_) |
| 196 wcv_holder_->native_view() == web_contents_->GetView()->GetNativeView()) { | |
| 197 return; | 246 return; |
| 198 } | |
| 199 | 247 |
| 200 if (web_contents_) { | 248 const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ? |
| 201 wcv_holder_->Attach(web_contents_->GetView()->GetNativeView()); | 249 web_contents_->GetFullscreenRenderWidgetHostView()->GetNativeView() : |
| 250 web_contents_->GetView()->GetNativeView(); |
| 251 if (wcv_holder_->native_view() == view_to_attach) |
| 252 return; |
| 253 wcv_holder_->Attach(view_to_attach); |
| 202 | 254 |
| 203 // The WebContentsView will not be focused automatically when it is | 255 // The view will not be focused automatically when it is attached, so we need |
| 204 // attached, so we need to pass on focus to it if the FocusManager thinks | 256 // to pass on focus to it if the FocusManager thinks the view is focused. Note |
| 205 // the WebView is focused. Note that not every Widget has a focus manager. | 257 // that not every Widget has a focus manager. |
| 206 FocusManager* focus_manager = GetFocusManager(); | 258 FocusManager* const focus_manager = GetFocusManager(); |
| 207 if (focus_manager && focus_manager->GetFocusedView() == this) | 259 if (focus_manager && focus_manager->GetFocusedView() == this) |
| 208 web_contents_->GetView()->Focus(); | 260 OnFocus(); |
| 209 | 261 |
| 210 registrar_.Add( | 262 registrar_.Add( |
| 211 this, | 263 this, |
| 212 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, | 264 content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, |
| 213 content::Source<content::NavigationController>( | 265 content::Source<content::NavigationController>( |
| 214 &web_contents_->GetController())); | 266 &web_contents_->GetController())); |
| 215 registrar_.Add( | 267 registrar_.Add( |
| 216 this, | 268 this, |
| 217 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 269 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 218 content::Source<content::WebContents>(web_contents_)); | 270 content::Source<content::WebContents>(web_contents_)); |
| 219 } | |
| 220 | 271 |
| 221 #if defined(OS_WIN) && defined(USE_AURA) | 272 #if defined(OS_WIN) && defined(USE_AURA) |
| 222 web_contents_->SetParentNativeViewAccessible( | 273 if (!is_embedding_fullscreen_widget_) { |
| 223 parent()->GetNativeViewAccessible()); | 274 web_contents_->SetParentNativeViewAccessible( |
| 275 parent()->GetNativeViewAccessible()); |
| 276 } |
| 224 #endif | 277 #endif |
| 225 } | 278 } |
| 226 | 279 |
| 227 void WebView::DetachWebContents() { | 280 void WebView::DetachWebContents() { |
| 228 if (web_contents_) { | 281 if (web_contents_) { |
| 229 wcv_holder_->Detach(); | 282 wcv_holder_->Detach(); |
| 230 #if defined(OS_WIN) && !defined(USE_AURA) | 283 #if defined(OS_WIN) |
| 231 // TODO(beng): This should either not be necessary, or be done implicitly by | 284 if (!is_embedding_fullscreen_widget_) { |
| 232 // NativeViewHostWin on Detach(). As it stands, this is needed so that the | 285 #if !defined(USE_AURA) |
| 233 // view of the detached contents knows to tell the renderer it's been | 286 // TODO(beng): This should either not be necessary, or be done implicitly |
| 234 // hidden. | 287 // by NativeViewHostWin on Detach(). As it stands, this is needed so that |
| 235 // | 288 // 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 | 289 // hidden. |
| 237 // calling member functions on a half-destroyed WebContents. | 290 // |
| 238 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); | 291 // Moving this out of here would also mean we wouldn't be potentially |
| 239 #elif defined(OS_WIN) && defined(USE_AURA) | 292 // calling member functions on a half-destroyed WebContents. |
| 240 web_contents_->SetParentNativeViewAccessible(NULL); | 293 ShowWindow(web_contents_->GetView()->GetNativeView(), SW_HIDE); |
| 294 #else |
| 295 web_contents_->SetParentNativeViewAccessible(NULL); |
| 296 #endif |
| 297 } |
| 241 #endif | 298 #endif |
| 242 } | 299 } |
| 243 registrar_.RemoveAll(); | 300 registrar_.RemoveAll(); |
| 244 } | 301 } |
| 245 | 302 |
| 246 void WebView::RenderViewHostChanged(content::RenderViewHost* old_host, | 303 void WebView::ReattachForFullscreenChange(bool enter_fullscreen) { |
| 247 content::RenderViewHost* new_host) { | 304 DetachWebContents(); |
| 248 if (GetFocusManager()->GetFocusedView() == this) | 305 is_embedding_fullscreen_widget_ = enter_fullscreen && |
| 249 web_contents_->GetView()->Focus(); | 306 web_contents_ && web_contents_->GetFullscreenRenderWidgetHostView(); |
| 250 } | 307 AttachWebContents(); |
| 251 | |
| 252 void WebView::WebContentsDestroyed(content::WebContents* web_contents) { | |
| 253 DCHECK(web_contents == web_contents_); | |
| 254 SetWebContents(NULL); | |
| 255 } | 308 } |
| 256 | 309 |
| 257 content::WebContents* WebView::CreateWebContents( | 310 content::WebContents* WebView::CreateWebContents( |
| 258 content::BrowserContext* browser_context, | 311 content::BrowserContext* browser_context, |
| 259 content::SiteInstance* site_instance) { | 312 content::SiteInstance* site_instance) { |
| 260 content::WebContents* contents = NULL; | 313 content::WebContents* contents = NULL; |
| 261 if (ViewsDelegate::views_delegate) { | 314 if (ViewsDelegate::views_delegate) { |
| 262 contents = ViewsDelegate::views_delegate->CreateWebContents( | 315 contents = ViewsDelegate::views_delegate->CreateWebContents( |
| 263 browser_context, site_instance); | 316 browser_context, site_instance); |
| 264 } | 317 } |
| 265 | 318 |
| 266 if (!contents) { | 319 if (!contents) { |
| 267 content::WebContents::CreateParams create_params( | 320 content::WebContents::CreateParams create_params( |
| 268 browser_context, site_instance); | 321 browser_context, site_instance); |
| 269 return content::WebContents::Create(create_params); | 322 return content::WebContents::Create(create_params); |
| 270 } | 323 } |
| 271 | 324 |
| 272 return contents; | 325 return contents; |
| 273 } | 326 } |
| 274 | 327 |
| 275 } // namespace views | 328 } // namespace views |
| OLD | NEW |