Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "content/browser/web_contents/interstitial_page_impl.h" |
| 6 | |
| 7 | #include <vector> |
| 8 | |
| 9 | #include "base/bind.h" |
| 10 | #include "base/compiler_specific.h" |
Ben Murdoch | 9ab5563 | 2013-07-18 11:57:30 +0100 | [diff] [blame] | 11 | #include "base/message_loop/message_loop.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 12 | #include "base/strings/string_util.h" |
| 13 | #include "base/strings/utf_string_conversions.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 14 | #include "base/threading/thread.h" |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 15 | #include "content/browser/dom_storage/dom_storage_context_wrapper.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 16 | #include "content/browser/dom_storage/session_storage_namespace_impl.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 17 | #include "content/browser/loader/resource_dispatcher_host_impl.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 18 | #include "content/browser/renderer_host/render_process_host_impl.h" |
| 19 | #include "content/browser/renderer_host/render_view_host_impl.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 20 | #include "content/browser/site_instance_impl.h" |
| 21 | #include "content/browser/web_contents/navigation_controller_impl.h" |
| 22 | #include "content/browser/web_contents/navigation_entry_impl.h" |
| 23 | #include "content/browser/web_contents/web_contents_impl.h" |
| 24 | #include "content/common/view_messages.h" |
| 25 | #include "content/port/browser/render_view_host_delegate_view.h" |
| 26 | #include "content/port/browser/render_widget_host_view_port.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 27 | #include "content/port/browser/web_contents_view_port.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 28 | #include "content/public/browser/browser_context.h" |
| 29 | #include "content/public/browser/browser_thread.h" |
| 30 | #include "content/public/browser/content_browser_client.h" |
| 31 | #include "content/public/browser/dom_operation_notification_details.h" |
| 32 | #include "content/public/browser/interstitial_page_delegate.h" |
| 33 | #include "content/public/browser/invalidate_type.h" |
| 34 | #include "content/public/browser/notification_service.h" |
| 35 | #include "content/public/browser/notification_source.h" |
| 36 | #include "content/public/browser/storage_partition.h" |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 37 | #include "content/public/browser/web_contents_delegate.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 38 | #include "content/public/common/bindings_policy.h" |
| 39 | #include "content/public/common/page_transition_types.h" |
| 40 | #include "net/base/escape.h" |
| 41 | #include "net/url_request/url_request_context_getter.h" |
| 42 | |
| 43 | using WebKit::WebDragOperation; |
| 44 | using WebKit::WebDragOperationsMask; |
| 45 | |
| 46 | namespace content { |
| 47 | namespace { |
| 48 | |
| 49 | void ResourceRequestHelper(ResourceDispatcherHostImpl* rdh, |
| 50 | int process_id, |
| 51 | int render_view_host_id, |
| 52 | ResourceRequestAction action) { |
| 53 | switch (action) { |
| 54 | case BLOCK: |
| 55 | rdh->BlockRequestsForRoute(process_id, render_view_host_id); |
| 56 | break; |
| 57 | case RESUME: |
| 58 | rdh->ResumeBlockedRequestsForRoute(process_id, render_view_host_id); |
| 59 | break; |
| 60 | case CANCEL: |
| 61 | rdh->CancelBlockedRequestsForRoute(process_id, render_view_host_id); |
| 62 | break; |
| 63 | default: |
| 64 | NOTREACHED(); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | } // namespace |
| 69 | |
| 70 | class InterstitialPageImpl::InterstitialPageRVHDelegateView |
| 71 | : public RenderViewHostDelegateView { |
| 72 | public: |
| 73 | explicit InterstitialPageRVHDelegateView(InterstitialPageImpl* page); |
| 74 | |
| 75 | // RenderViewHostDelegateView implementation: |
| 76 | virtual void ShowPopupMenu(const gfx::Rect& bounds, |
| 77 | int item_height, |
| 78 | double item_font_size, |
| 79 | int selected_item, |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 80 | const std::vector<MenuItem>& items, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 81 | bool right_aligned, |
| 82 | bool allow_multiple_selection) OVERRIDE; |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 83 | virtual void StartDragging(const DropData& drop_data, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 84 | WebDragOperationsMask operations_allowed, |
| 85 | const gfx::ImageSkia& image, |
| 86 | const gfx::Vector2d& image_offset, |
| 87 | const DragEventSourceInfo& event_info) OVERRIDE; |
| 88 | virtual void UpdateDragCursor(WebDragOperation operation) OVERRIDE; |
| 89 | virtual void GotFocus() OVERRIDE; |
| 90 | virtual void TakeFocus(bool reverse) OVERRIDE; |
| 91 | virtual void OnFindReply(int request_id, |
| 92 | int number_of_matches, |
| 93 | const gfx::Rect& selection_rect, |
| 94 | int active_match_ordinal, |
| 95 | bool final_update); |
| 96 | |
| 97 | private: |
| 98 | InterstitialPageImpl* interstitial_page_; |
| 99 | |
| 100 | DISALLOW_COPY_AND_ASSIGN(InterstitialPageRVHDelegateView); |
| 101 | }; |
| 102 | |
| 103 | |
| 104 | // We keep a map of the various blocking pages shown as the UI tests need to |
| 105 | // be able to retrieve them. |
| 106 | typedef std::map<WebContents*, InterstitialPageImpl*> InterstitialPageMap; |
| 107 | static InterstitialPageMap* g_web_contents_to_interstitial_page; |
| 108 | |
| 109 | // Initializes g_web_contents_to_interstitial_page in a thread-safe manner. |
| 110 | // Should be called before accessing g_web_contents_to_interstitial_page. |
| 111 | static void InitInterstitialPageMap() { |
| 112 | if (!g_web_contents_to_interstitial_page) |
| 113 | g_web_contents_to_interstitial_page = new InterstitialPageMap; |
| 114 | } |
| 115 | |
| 116 | InterstitialPage* InterstitialPage::Create(WebContents* web_contents, |
| 117 | bool new_navigation, |
| 118 | const GURL& url, |
| 119 | InterstitialPageDelegate* delegate) { |
| 120 | return new InterstitialPageImpl(web_contents, new_navigation, url, delegate); |
| 121 | } |
| 122 | |
| 123 | InterstitialPage* InterstitialPage::GetInterstitialPage( |
| 124 | WebContents* web_contents) { |
| 125 | InitInterstitialPageMap(); |
| 126 | InterstitialPageMap::const_iterator iter = |
| 127 | g_web_contents_to_interstitial_page->find(web_contents); |
| 128 | if (iter == g_web_contents_to_interstitial_page->end()) |
| 129 | return NULL; |
| 130 | |
| 131 | return iter->second; |
| 132 | } |
| 133 | |
| 134 | InterstitialPageImpl::InterstitialPageImpl(WebContents* web_contents, |
| 135 | bool new_navigation, |
| 136 | const GURL& url, |
| 137 | InterstitialPageDelegate* delegate) |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 138 | : WebContentsObserver(web_contents), |
| 139 | web_contents_(static_cast<WebContentsImpl*>(web_contents)), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 140 | url_(url), |
| 141 | new_navigation_(new_navigation), |
| 142 | should_discard_pending_nav_entry_(new_navigation), |
| 143 | reload_on_dont_proceed_(false), |
| 144 | enabled_(true), |
| 145 | action_taken_(NO_ACTION), |
| 146 | render_view_host_(NULL), |
| 147 | original_child_id_(web_contents->GetRenderProcessHost()->GetID()), |
| 148 | original_rvh_id_(web_contents->GetRenderViewHost()->GetRoutingID()), |
| 149 | should_revert_web_contents_title_(false), |
| 150 | web_contents_was_loading_(false), |
| 151 | resource_dispatcher_host_notified_(false), |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 152 | rvh_delegate_view_(new InterstitialPageRVHDelegateView(this)), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 153 | create_view_(true), |
| 154 | delegate_(delegate), |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 155 | weak_ptr_factory_(this) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 156 | InitInterstitialPageMap(); |
| 157 | // It would be inconsistent to create an interstitial with no new navigation |
| 158 | // (which is the case when the interstitial was triggered by a sub-resource on |
| 159 | // a page) when we have a pending entry (in the process of loading a new top |
| 160 | // frame). |
| 161 | DCHECK(new_navigation || !web_contents->GetController().GetPendingEntry()); |
| 162 | } |
| 163 | |
| 164 | InterstitialPageImpl::~InterstitialPageImpl() { |
| 165 | } |
| 166 | |
| 167 | void InterstitialPageImpl::Show() { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 168 | if (!enabled()) |
| 169 | return; |
| 170 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 171 | // If an interstitial is already showing or about to be shown, close it before |
| 172 | // showing the new one. |
| 173 | // Be careful not to take an action on the old interstitial more than once. |
| 174 | InterstitialPageMap::const_iterator iter = |
| 175 | g_web_contents_to_interstitial_page->find(web_contents_); |
| 176 | if (iter != g_web_contents_to_interstitial_page->end()) { |
| 177 | InterstitialPageImpl* interstitial = iter->second; |
| 178 | if (interstitial->action_taken_ != NO_ACTION) { |
| 179 | interstitial->Hide(); |
| 180 | } else { |
| 181 | // If we are currently showing an interstitial page for which we created |
| 182 | // a transient entry and a new interstitial is shown as the result of a |
| 183 | // new browser initiated navigation, then that transient entry has already |
| 184 | // been discarded and a new pending navigation entry created. |
| 185 | // So we should not discard that new pending navigation entry. |
| 186 | // See http://crbug.com/9791 |
| 187 | if (new_navigation_ && interstitial->new_navigation_) |
| 188 | interstitial->should_discard_pending_nav_entry_= false; |
| 189 | interstitial->DontProceed(); |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | // Block the resource requests for the render view host while it is hidden. |
| 194 | TakeActionOnResourceDispatcher(BLOCK); |
| 195 | // We need to be notified when the RenderViewHost is destroyed so we can |
| 196 | // cancel the blocked requests. We cannot do that on |
| 197 | // NOTIFY_WEB_CONTENTS_DESTROYED as at that point the RenderViewHost has |
| 198 | // already been destroyed. |
| 199 | notification_registrar_.Add( |
| 200 | this, NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED, |
| 201 | Source<RenderWidgetHost>(web_contents_->GetRenderViewHost())); |
| 202 | |
| 203 | // Update the g_web_contents_to_interstitial_page map. |
| 204 | iter = g_web_contents_to_interstitial_page->find(web_contents_); |
| 205 | DCHECK(iter == g_web_contents_to_interstitial_page->end()); |
| 206 | (*g_web_contents_to_interstitial_page)[web_contents_] = this; |
| 207 | |
| 208 | if (new_navigation_) { |
| 209 | NavigationEntryImpl* entry = new NavigationEntryImpl; |
| 210 | entry->SetURL(url_); |
| 211 | entry->SetVirtualURL(url_); |
| 212 | entry->set_page_type(PAGE_TYPE_INTERSTITIAL); |
| 213 | |
| 214 | // Give delegates a chance to set some states on the navigation entry. |
| 215 | delegate_->OverrideEntry(entry); |
| 216 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 217 | web_contents_->GetController().SetTransientEntry(entry); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 218 | } |
| 219 | |
| 220 | DCHECK(!render_view_host_); |
| 221 | render_view_host_ = static_cast<RenderViewHostImpl*>(CreateRenderViewHost()); |
| 222 | CreateWebContentsView(); |
| 223 | |
| 224 | std::string data_url = "data:text/html;charset=utf-8," + |
| 225 | net::EscapePath(delegate_->GetHTMLContents()); |
| 226 | render_view_host_->NavigateToURL(GURL(data_url)); |
| 227 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 228 | notification_registrar_.Add(this, NOTIFICATION_NAV_ENTRY_PENDING, |
| 229 | Source<NavigationController>(&web_contents_->GetController())); |
| 230 | notification_registrar_.Add( |
| 231 | this, NOTIFICATION_DOM_OPERATION_RESPONSE, |
| 232 | Source<RenderViewHost>(render_view_host_)); |
| 233 | } |
| 234 | |
| 235 | void InterstitialPageImpl::Hide() { |
| 236 | // We may have already been hidden, and are just waiting to be deleted. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 237 | // We can't check for enabled() here, because some callers have already |
| 238 | // called Disable. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 239 | if (!render_view_host_) |
| 240 | return; |
| 241 | |
| 242 | Disable(); |
| 243 | |
| 244 | RenderWidgetHostView* old_view = |
| 245 | web_contents_->GetRenderViewHost()->GetView(); |
| 246 | if (web_contents_->GetInterstitialPage() == this && |
| 247 | old_view && !old_view->IsShowing()) { |
| 248 | // Show the original RVH since we're going away. Note it might not exist if |
| 249 | // the renderer crashed while the interstitial was showing. |
| 250 | // Note that it is important that we don't call Show() if the view is |
| 251 | // already showing. That would result in bad things (unparented HWND on |
| 252 | // Windows for example) happening. |
| 253 | old_view->Show(); |
| 254 | } |
| 255 | |
| 256 | // If the focus was on the interstitial, let's keep it to the page. |
| 257 | // (Note that in unit-tests the RVH may not have a view). |
| 258 | if (render_view_host_->GetView() && |
| 259 | render_view_host_->GetView()->HasFocus() && |
| 260 | web_contents_->GetRenderViewHost()->GetView()) { |
| 261 | RenderWidgetHostViewPort::FromRWHV( |
| 262 | web_contents_->GetRenderViewHost()->GetView())->Focus(); |
| 263 | } |
| 264 | |
| 265 | // Shutdown the RVH asynchronously, as we may have been called from a RVH |
| 266 | // delegate method, and we can't delete the RVH out from under itself. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 267 | base::MessageLoop::current()->PostNonNestableTask( |
| 268 | FROM_HERE, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 269 | base::Bind(&InterstitialPageImpl::Shutdown, |
| 270 | weak_ptr_factory_.GetWeakPtr(), |
| 271 | render_view_host_)); |
| 272 | render_view_host_ = NULL; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 273 | web_contents_->DetachInterstitialPage(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 274 | // Let's revert to the original title if necessary. |
| 275 | NavigationEntry* entry = web_contents_->GetController().GetActiveEntry(); |
| 276 | if (!new_navigation_ && should_revert_web_contents_title_) { |
| 277 | entry->SetTitle(original_web_contents_title_); |
| 278 | web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE); |
| 279 | } |
| 280 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 281 | InterstitialPageMap::iterator iter = |
| 282 | g_web_contents_to_interstitial_page->find(web_contents_); |
| 283 | DCHECK(iter != g_web_contents_to_interstitial_page->end()); |
| 284 | if (iter != g_web_contents_to_interstitial_page->end()) |
| 285 | g_web_contents_to_interstitial_page->erase(iter); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 286 | |
| 287 | // Clear the WebContents pointer, because it may now be deleted. |
| 288 | // This signifies that we are in the process of shutting down. |
| 289 | web_contents_ = NULL; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | void InterstitialPageImpl::Observe( |
| 293 | int type, |
| 294 | const NotificationSource& source, |
| 295 | const NotificationDetails& details) { |
| 296 | switch (type) { |
| 297 | case NOTIFICATION_NAV_ENTRY_PENDING: |
| 298 | // We are navigating away from the interstitial (the user has typed a URL |
| 299 | // in the location bar or clicked a bookmark). Make sure clicking on the |
| 300 | // interstitial will have no effect. Also cancel any blocked requests |
| 301 | // on the ResourceDispatcherHost. Note that when we get this notification |
| 302 | // the RenderViewHost has not yet navigated so we'll unblock the |
| 303 | // RenderViewHost before the resource request for the new page we are |
| 304 | // navigating arrives in the ResourceDispatcherHost. This ensures that |
| 305 | // request won't be blocked if the same RenderViewHost was used for the |
| 306 | // new navigation. |
| 307 | Disable(); |
| 308 | TakeActionOnResourceDispatcher(CANCEL); |
| 309 | break; |
| 310 | case NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: |
| 311 | if (action_taken_ == NO_ACTION) { |
| 312 | // The RenderViewHost is being destroyed (as part of the tab being |
| 313 | // closed); make sure we clear the blocked requests. |
| 314 | RenderViewHost* rvh = static_cast<RenderViewHost*>( |
| 315 | static_cast<RenderViewHostImpl*>( |
| 316 | RenderWidgetHostImpl::From( |
| 317 | Source<RenderWidgetHost>(source).ptr()))); |
| 318 | DCHECK(rvh->GetProcess()->GetID() == original_child_id_ && |
| 319 | rvh->GetRoutingID() == original_rvh_id_); |
| 320 | TakeActionOnResourceDispatcher(CANCEL); |
| 321 | } |
| 322 | break; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 323 | case NOTIFICATION_DOM_OPERATION_RESPONSE: |
| 324 | if (enabled()) { |
| 325 | Details<DomOperationNotificationDetails> dom_op_details( |
| 326 | details); |
| 327 | delegate_->CommandReceived(dom_op_details->json); |
| 328 | } |
| 329 | break; |
| 330 | default: |
| 331 | NOTREACHED(); |
| 332 | } |
| 333 | } |
| 334 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 335 | void InterstitialPageImpl::NavigationEntryCommitted( |
| 336 | const LoadCommittedDetails& load_details) { |
| 337 | OnNavigatingAwayOrTabClosing(); |
| 338 | } |
| 339 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 340 | void InterstitialPageImpl::WebContentsDestroyed(WebContents* web_contents) { |
| 341 | OnNavigatingAwayOrTabClosing(); |
| 342 | } |
| 343 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 344 | RenderViewHostDelegateView* InterstitialPageImpl::GetDelegateView() { |
| 345 | return rvh_delegate_view_.get(); |
| 346 | } |
| 347 | |
| 348 | const GURL& InterstitialPageImpl::GetURL() const { |
| 349 | return url_; |
| 350 | } |
| 351 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 352 | void InterstitialPageImpl::RenderViewTerminated( |
| 353 | RenderViewHost* render_view_host, |
| 354 | base::TerminationStatus status, |
| 355 | int error_code) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 356 | // Our renderer died. This should not happen in normal cases. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 357 | // If we haven't already started shutdown, just dismiss the interstitial. |
| 358 | // We cannot check for enabled() here, because we may have called Disable |
| 359 | // without calling Hide. |
| 360 | if (render_view_host_) |
| 361 | DontProceed(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 362 | } |
| 363 | |
| 364 | void InterstitialPageImpl::DidNavigate( |
| 365 | RenderViewHost* render_view_host, |
| 366 | const ViewHostMsg_FrameNavigate_Params& params) { |
| 367 | // A fast user could have navigated away from the page that triggered the |
| 368 | // interstitial while the interstitial was loading, that would have disabled |
| 369 | // us. In that case we can dismiss ourselves. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 370 | if (!enabled()) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 371 | DontProceed(); |
| 372 | return; |
| 373 | } |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 374 | if (PageTransitionCoreTypeIs(params.transition, |
| 375 | PAGE_TRANSITION_AUTO_SUBFRAME)) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 376 | // No need to handle navigate message from iframe in the interstitial page. |
| 377 | return; |
| 378 | } |
| 379 | |
| 380 | // The RenderViewHost has loaded its contents, we can show it now. |
| 381 | render_view_host_->GetView()->Show(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 382 | web_contents_->AttachInterstitialPage(this); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 383 | |
| 384 | RenderWidgetHostView* rwh_view = |
| 385 | web_contents_->GetRenderViewHost()->GetView(); |
| 386 | |
| 387 | // The RenderViewHost may already have crashed before we even get here. |
| 388 | if (rwh_view) { |
| 389 | // If the page has focus, focus the interstitial. |
| 390 | if (rwh_view->HasFocus()) |
| 391 | Focus(); |
| 392 | |
| 393 | // Hide the original RVH since we're showing the interstitial instead. |
| 394 | rwh_view->Hide(); |
| 395 | } |
| 396 | |
| 397 | // Notify the tab we are not loading so the throbber is stopped. It also |
| 398 | // causes a NOTIFY_LOAD_STOP notification, that the AutomationProvider (used |
| 399 | // by the UI tests) expects to consider a navigation as complete. Without |
| 400 | // this, navigating in a UI test to a URL that triggers an interstitial would |
| 401 | // hang. |
| 402 | web_contents_was_loading_ = web_contents_->IsLoading(); |
| 403 | web_contents_->SetIsLoading(false, NULL); |
| 404 | } |
| 405 | |
| 406 | void InterstitialPageImpl::UpdateTitle( |
| 407 | RenderViewHost* render_view_host, |
| 408 | int32 page_id, |
| 409 | const string16& title, |
| 410 | base::i18n::TextDirection title_direction) { |
| 411 | if (!enabled()) |
| 412 | return; |
| 413 | |
| 414 | DCHECK(render_view_host == render_view_host_); |
| 415 | NavigationEntry* entry = web_contents_->GetController().GetActiveEntry(); |
| 416 | if (!entry) { |
| 417 | // Crash reports from the field indicate this can be NULL. |
| 418 | // This is unexpected as InterstitialPages constructed with the |
| 419 | // new_navigation flag set to true create a transient navigation entry |
| 420 | // (that is returned as the active entry). And the only case so far of |
| 421 | // interstitial created with that flag set to false is with the |
| 422 | // SafeBrowsingBlockingPage, when the resource triggering the interstitial |
| 423 | // is a sub-resource, meaning the main page has already been loaded and a |
| 424 | // navigation entry should have been created. |
| 425 | NOTREACHED(); |
| 426 | return; |
| 427 | } |
| 428 | |
| 429 | // If this interstitial is shown on an existing navigation entry, we'll need |
| 430 | // to remember its title so we can revert to it when hidden. |
| 431 | if (!new_navigation_ && !should_revert_web_contents_title_) { |
| 432 | original_web_contents_title_ = entry->GetTitle(); |
| 433 | should_revert_web_contents_title_ = true; |
| 434 | } |
| 435 | // TODO(evan): make use of title_direction. |
| 436 | // http://code.google.com/p/chromium/issues/detail?id=27094 |
| 437 | entry->SetTitle(title); |
| 438 | web_contents_->NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE); |
| 439 | } |
| 440 | |
| 441 | RendererPreferences InterstitialPageImpl::GetRendererPrefs( |
| 442 | BrowserContext* browser_context) const { |
| 443 | delegate_->OverrideRendererPrefs(&renderer_preferences_); |
| 444 | return renderer_preferences_; |
| 445 | } |
| 446 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 447 | WebPreferences InterstitialPageImpl::GetWebkitPrefs() { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 448 | if (!enabled()) |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 449 | return WebPreferences(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 450 | |
| 451 | return WebContentsImpl::GetWebkitPrefs(render_view_host_, url_); |
| 452 | } |
| 453 | |
| 454 | void InterstitialPageImpl::RenderWidgetDeleted( |
| 455 | RenderWidgetHostImpl* render_widget_host) { |
| 456 | delete this; |
| 457 | } |
| 458 | |
| 459 | bool InterstitialPageImpl::PreHandleKeyboardEvent( |
| 460 | const NativeWebKeyboardEvent& event, |
| 461 | bool* is_keyboard_shortcut) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 462 | if (!enabled()) |
| 463 | return false; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 464 | return web_contents_->PreHandleKeyboardEvent(event, is_keyboard_shortcut); |
| 465 | } |
| 466 | |
| 467 | void InterstitialPageImpl::HandleKeyboardEvent( |
| 468 | const NativeWebKeyboardEvent& event) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 469 | if (enabled()) |
| 470 | web_contents_->HandleKeyboardEvent(event); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 471 | } |
| 472 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 473 | #if defined(OS_WIN) && defined(USE_AURA) |
| 474 | gfx::NativeViewAccessible |
| 475 | InterstitialPageImpl::GetParentNativeViewAccessible() { |
| 476 | return web_contents_->GetParentNativeViewAccessible(); |
| 477 | } |
| 478 | #endif |
| 479 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 480 | WebContents* InterstitialPageImpl::web_contents() const { |
| 481 | return web_contents_; |
| 482 | } |
| 483 | |
| 484 | RenderViewHost* InterstitialPageImpl::CreateRenderViewHost() { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 485 | if (!enabled()) |
| 486 | return NULL; |
| 487 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 488 | // Interstitial pages don't want to share the session storage so we mint a |
| 489 | // new one. |
| 490 | BrowserContext* browser_context = web_contents()->GetBrowserContext(); |
| 491 | scoped_refptr<SiteInstance> site_instance = |
| 492 | SiteInstance::Create(browser_context); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 493 | DOMStorageContextWrapper* dom_storage_context = |
| 494 | static_cast<DOMStorageContextWrapper*>( |
| 495 | BrowserContext::GetStoragePartition( |
| 496 | browser_context, site_instance.get())->GetDOMStorageContext()); |
Ben Murdoch | a3f7b4e | 2013-07-24 10:36:34 +0100 | [diff] [blame] | 497 | session_storage_namespace_ = |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 498 | new SessionStorageNamespaceImpl(dom_storage_context); |
| 499 | |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 500 | RenderViewHostImpl* render_view_host = |
| 501 | new RenderViewHostImpl(site_instance.get(), |
| 502 | this, |
| 503 | this, |
| 504 | MSG_ROUTING_NONE, |
| 505 | MSG_ROUTING_NONE, |
Ben Murdoch | a3f7b4e | 2013-07-24 10:36:34 +0100 | [diff] [blame] | 506 | false); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 507 | web_contents_->RenderViewForInterstitialPageCreated(render_view_host); |
| 508 | return render_view_host; |
| 509 | } |
| 510 | |
| 511 | WebContentsView* InterstitialPageImpl::CreateWebContentsView() { |
| 512 | if (!enabled() || !create_view_) |
| 513 | return NULL; |
| 514 | WebContentsView* web_contents_view = web_contents()->GetView(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 515 | WebContentsViewPort* web_contents_view_port = |
| 516 | static_cast<WebContentsViewPort*>(web_contents_view); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 517 | RenderWidgetHostView* view = |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 518 | web_contents_view_port->CreateViewForWidget(render_view_host_); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 519 | render_view_host_->SetView(view); |
| 520 | render_view_host_->AllowBindings(BINDINGS_POLICY_DOM_AUTOMATION); |
| 521 | |
| 522 | int32 max_page_id = web_contents()-> |
| 523 | GetMaxPageIDForSiteInstance(render_view_host_->GetSiteInstance()); |
| 524 | render_view_host_->CreateRenderView(string16(), |
| 525 | MSG_ROUTING_NONE, |
| 526 | max_page_id); |
| 527 | view->SetSize(web_contents_view->GetContainerSize()); |
| 528 | // Don't show the interstitial until we have navigated to it. |
| 529 | view->Hide(); |
| 530 | return web_contents_view; |
| 531 | } |
| 532 | |
| 533 | void InterstitialPageImpl::Proceed() { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 534 | // Don't repeat this if we are already shutting down. We cannot check for |
| 535 | // enabled() here, because we may have called Disable without calling Hide. |
| 536 | if (!render_view_host_) |
| 537 | return; |
| 538 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 539 | if (action_taken_ != NO_ACTION) { |
| 540 | NOTREACHED(); |
| 541 | return; |
| 542 | } |
| 543 | Disable(); |
| 544 | action_taken_ = PROCEED_ACTION; |
| 545 | |
| 546 | // Resumes the throbber, if applicable. |
| 547 | if (web_contents_was_loading_) |
| 548 | web_contents_->SetIsLoading(true, NULL); |
| 549 | |
| 550 | // If this is a new navigation, the old page is going away, so we cancel any |
| 551 | // blocked requests for it. If it is not a new navigation, then it means the |
| 552 | // interstitial was shown as a result of a resource loading in the page. |
| 553 | // Since the user wants to proceed, we'll let any blocked request go through. |
| 554 | if (new_navigation_) |
| 555 | TakeActionOnResourceDispatcher(CANCEL); |
| 556 | else |
| 557 | TakeActionOnResourceDispatcher(RESUME); |
| 558 | |
| 559 | // No need to hide if we are a new navigation, we'll get hidden when the |
| 560 | // navigation is committed. |
| 561 | if (!new_navigation_) { |
| 562 | Hide(); |
| 563 | delegate_->OnProceed(); |
| 564 | return; |
| 565 | } |
| 566 | |
| 567 | delegate_->OnProceed(); |
| 568 | } |
| 569 | |
| 570 | void InterstitialPageImpl::DontProceed() { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 571 | // Don't repeat this if we are already shutting down. We cannot check for |
| 572 | // enabled() here, because we may have called Disable without calling Hide. |
| 573 | if (!render_view_host_) |
| 574 | return; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 575 | DCHECK(action_taken_ != DONT_PROCEED_ACTION); |
| 576 | |
| 577 | Disable(); |
| 578 | action_taken_ = DONT_PROCEED_ACTION; |
| 579 | |
| 580 | // If this is a new navigation, we are returning to the original page, so we |
| 581 | // resume blocked requests for it. If it is not a new navigation, then it |
| 582 | // means the interstitial was shown as a result of a resource loading in the |
| 583 | // page and we won't return to the original page, so we cancel blocked |
| 584 | // requests in that case. |
| 585 | if (new_navigation_) |
| 586 | TakeActionOnResourceDispatcher(RESUME); |
| 587 | else |
| 588 | TakeActionOnResourceDispatcher(CANCEL); |
| 589 | |
| 590 | if (should_discard_pending_nav_entry_) { |
| 591 | // Since no navigation happens we have to discard the transient entry |
| 592 | // explicitely. Note that by calling DiscardNonCommittedEntries() we also |
| 593 | // discard the pending entry, which is what we want, since the navigation is |
| 594 | // cancelled. |
| 595 | web_contents_->GetController().DiscardNonCommittedEntries(); |
| 596 | } |
| 597 | |
| 598 | if (reload_on_dont_proceed_) |
| 599 | web_contents_->GetController().Reload(true); |
| 600 | |
| 601 | Hide(); |
| 602 | delegate_->OnDontProceed(); |
| 603 | } |
| 604 | |
| 605 | void InterstitialPageImpl::CancelForNavigation() { |
| 606 | // The user is trying to navigate away. We should unblock the renderer and |
| 607 | // disable the interstitial, but keep it visible until the navigation |
| 608 | // completes. |
| 609 | Disable(); |
| 610 | // If this interstitial was shown for a new navigation, allow any navigations |
| 611 | // on the original page to resume (e.g., subresource requests, XHRs, etc). |
| 612 | // Otherwise, cancel the pending, possibly dangerous navigations. |
| 613 | if (new_navigation_) |
| 614 | TakeActionOnResourceDispatcher(RESUME); |
| 615 | else |
| 616 | TakeActionOnResourceDispatcher(CANCEL); |
| 617 | } |
| 618 | |
| 619 | void InterstitialPageImpl::SetSize(const gfx::Size& size) { |
| 620 | if (!enabled()) |
| 621 | return; |
| 622 | #if !defined(OS_MACOSX) |
| 623 | // When a tab is closed, we might be resized after our view was NULLed |
| 624 | // (typically if there was an info-bar). |
| 625 | if (render_view_host_->GetView()) |
| 626 | render_view_host_->GetView()->SetSize(size); |
| 627 | #else |
| 628 | // TODO(port): Does Mac need to SetSize? |
| 629 | NOTIMPLEMENTED(); |
| 630 | #endif |
| 631 | } |
| 632 | |
| 633 | void InterstitialPageImpl::Focus() { |
| 634 | // Focus the native window. |
| 635 | if (!enabled()) |
| 636 | return; |
| 637 | RenderWidgetHostViewPort::FromRWHV(render_view_host_->GetView())->Focus(); |
| 638 | } |
| 639 | |
| 640 | void InterstitialPageImpl::FocusThroughTabTraversal(bool reverse) { |
| 641 | if (!enabled()) |
| 642 | return; |
| 643 | render_view_host_->SetInitialFocus(reverse); |
| 644 | } |
| 645 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 646 | RenderWidgetHostView* InterstitialPageImpl::GetView() { |
| 647 | return render_view_host_->GetView(); |
| 648 | } |
| 649 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 650 | RenderViewHost* InterstitialPageImpl::GetRenderViewHostForTesting() const { |
| 651 | return render_view_host_; |
| 652 | } |
| 653 | |
| 654 | #if defined(OS_ANDROID) |
| 655 | RenderViewHost* InterstitialPageImpl::GetRenderViewHost() const { |
| 656 | return render_view_host_; |
| 657 | } |
| 658 | #endif |
| 659 | |
| 660 | InterstitialPageDelegate* InterstitialPageImpl::GetDelegateForTesting() { |
| 661 | return delegate_.get(); |
| 662 | } |
| 663 | |
| 664 | void InterstitialPageImpl::DontCreateViewForTesting() { |
| 665 | create_view_ = false; |
| 666 | } |
| 667 | |
| 668 | gfx::Rect InterstitialPageImpl::GetRootWindowResizerRect() const { |
| 669 | return gfx::Rect(); |
| 670 | } |
| 671 | |
| 672 | void InterstitialPageImpl::CreateNewWindow( |
| 673 | int route_id, |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 674 | int main_frame_route_id, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 675 | const ViewHostMsg_CreateWindow_Params& params, |
| 676 | SessionStorageNamespace* session_storage_namespace) { |
| 677 | NOTREACHED() << "InterstitialPage does not support showing popups yet."; |
| 678 | } |
| 679 | |
| 680 | void InterstitialPageImpl::CreateNewWidget(int route_id, |
| 681 | WebKit::WebPopupType popup_type) { |
| 682 | NOTREACHED() << "InterstitialPage does not support showing drop-downs yet."; |
| 683 | } |
| 684 | |
| 685 | void InterstitialPageImpl::CreateNewFullscreenWidget(int route_id) { |
| 686 | NOTREACHED() |
| 687 | << "InterstitialPage does not support showing full screen popups."; |
| 688 | } |
| 689 | |
| 690 | void InterstitialPageImpl::ShowCreatedWindow(int route_id, |
| 691 | WindowOpenDisposition disposition, |
| 692 | const gfx::Rect& initial_pos, |
| 693 | bool user_gesture) { |
| 694 | NOTREACHED() << "InterstitialPage does not support showing popups yet."; |
| 695 | } |
| 696 | |
| 697 | void InterstitialPageImpl::ShowCreatedWidget(int route_id, |
| 698 | const gfx::Rect& initial_pos) { |
| 699 | NOTREACHED() << "InterstitialPage does not support showing drop-downs yet."; |
| 700 | } |
| 701 | |
| 702 | void InterstitialPageImpl::ShowCreatedFullscreenWidget(int route_id) { |
| 703 | NOTREACHED() |
| 704 | << "InterstitialPage does not support showing full screen popups."; |
| 705 | } |
| 706 | |
Ben Murdoch | a3f7b4e | 2013-07-24 10:36:34 +0100 | [diff] [blame] | 707 | SessionStorageNamespace* InterstitialPageImpl::GetSessionStorageNamespace( |
| 708 | SiteInstance* instance) { |
| 709 | return session_storage_namespace_.get(); |
| 710 | } |
| 711 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 712 | void InterstitialPageImpl::Disable() { |
| 713 | enabled_ = false; |
| 714 | } |
| 715 | |
| 716 | void InterstitialPageImpl::Shutdown(RenderViewHostImpl* render_view_host) { |
| 717 | render_view_host->Shutdown(); |
| 718 | // We are deleted now. |
| 719 | } |
| 720 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 721 | void InterstitialPageImpl::OnNavigatingAwayOrTabClosing() { |
| 722 | if (action_taken_ == NO_ACTION) { |
| 723 | // We are navigating away from the interstitial or closing a tab with an |
| 724 | // interstitial. Default to DontProceed(). We don't just call Hide as |
| 725 | // subclasses will almost certainly override DontProceed to do some work |
| 726 | // (ex: close pending connections). |
| 727 | DontProceed(); |
| 728 | } else { |
| 729 | // User decided to proceed and either the navigation was committed or |
| 730 | // the tab was closed before that. |
| 731 | Hide(); |
| 732 | } |
| 733 | } |
| 734 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 735 | void InterstitialPageImpl::TakeActionOnResourceDispatcher( |
| 736 | ResourceRequestAction action) { |
| 737 | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)) << |
| 738 | "TakeActionOnResourceDispatcher should be called on the main thread."; |
| 739 | |
| 740 | if (action == CANCEL || action == RESUME) { |
| 741 | if (resource_dispatcher_host_notified_) |
| 742 | return; |
| 743 | resource_dispatcher_host_notified_ = true; |
| 744 | } |
| 745 | |
| 746 | // The tab might not have a render_view_host if it was closed (in which case, |
| 747 | // we have taken care of the blocked requests when processing |
| 748 | // NOTIFY_RENDER_WIDGET_HOST_DESTROYED. |
| 749 | // Also we need to test there is a ResourceDispatcherHostImpl, as when unit- |
| 750 | // tests we don't have one. |
| 751 | RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(original_child_id_, |
| 752 | original_rvh_id_); |
| 753 | if (!rvh || !ResourceDispatcherHostImpl::Get()) |
| 754 | return; |
| 755 | |
| 756 | BrowserThread::PostTask( |
| 757 | BrowserThread::IO, |
| 758 | FROM_HERE, |
| 759 | base::Bind( |
| 760 | &ResourceRequestHelper, |
| 761 | ResourceDispatcherHostImpl::Get(), |
| 762 | original_child_id_, |
| 763 | original_rvh_id_, |
| 764 | action)); |
| 765 | } |
| 766 | |
| 767 | InterstitialPageImpl::InterstitialPageRVHDelegateView:: |
| 768 | InterstitialPageRVHDelegateView(InterstitialPageImpl* page) |
| 769 | : interstitial_page_(page) { |
| 770 | } |
| 771 | |
| 772 | void InterstitialPageImpl::InterstitialPageRVHDelegateView::ShowPopupMenu( |
| 773 | const gfx::Rect& bounds, |
| 774 | int item_height, |
| 775 | double item_font_size, |
| 776 | int selected_item, |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 777 | const std::vector<MenuItem>& items, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 778 | bool right_aligned, |
| 779 | bool allow_multiple_selection) { |
| 780 | NOTREACHED() << "InterstitialPage does not support showing popup menus."; |
| 781 | } |
| 782 | |
| 783 | void InterstitialPageImpl::InterstitialPageRVHDelegateView::StartDragging( |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 784 | const DropData& drop_data, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 785 | WebDragOperationsMask allowed_operations, |
| 786 | const gfx::ImageSkia& image, |
| 787 | const gfx::Vector2d& image_offset, |
| 788 | const DragEventSourceInfo& event_info) { |
| 789 | NOTREACHED() << "InterstitialPage does not support dragging yet."; |
| 790 | } |
| 791 | |
| 792 | void InterstitialPageImpl::InterstitialPageRVHDelegateView::UpdateDragCursor( |
| 793 | WebDragOperation) { |
| 794 | NOTREACHED() << "InterstitialPage does not support dragging yet."; |
| 795 | } |
| 796 | |
| 797 | void InterstitialPageImpl::InterstitialPageRVHDelegateView::GotFocus() { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 798 | WebContents* web_contents = interstitial_page_->web_contents(); |
| 799 | if (web_contents && web_contents->GetDelegate()) |
| 800 | web_contents->GetDelegate()->WebContentsFocused(web_contents); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 801 | } |
| 802 | |
| 803 | void InterstitialPageImpl::InterstitialPageRVHDelegateView::TakeFocus( |
| 804 | bool reverse) { |
| 805 | if (!interstitial_page_->web_contents()) |
| 806 | return; |
| 807 | WebContentsImpl* web_contents = |
| 808 | static_cast<WebContentsImpl*>(interstitial_page_->web_contents()); |
| 809 | if (!web_contents->GetDelegateView()) |
| 810 | return; |
| 811 | |
| 812 | web_contents->GetDelegateView()->TakeFocus(reverse); |
| 813 | } |
| 814 | |
| 815 | void InterstitialPageImpl::InterstitialPageRVHDelegateView::OnFindReply( |
| 816 | int request_id, int number_of_matches, const gfx::Rect& selection_rect, |
| 817 | int active_match_ordinal, bool final_update) { |
| 818 | } |
| 819 | |
| 820 | } // namespace content |