| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "chrome/browser/tab_contents/interstitial_page.h" | 5 #include "chrome/browser/tab_contents/interstitial_page.h" |
| 6 | 6 |
| 7 #include "chrome/browser/browser.h" | 7 #include "chrome/browser/browser.h" |
| 8 #include "chrome/browser/browser_list.h" | 8 #include "chrome/browser/browser_list.h" |
| 9 #include "chrome/browser/browser_resources.h" | 9 #include "chrome/browser/browser_resources.h" |
| 10 #include "chrome/browser/dom_operation_notification_details.h" | 10 #include "chrome/browser/dom_operation_notification_details.h" |
| 11 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" | 11 #include "chrome/browser/renderer_host/render_widget_host_view_win.h" |
| 12 #include "chrome/browser/tab_contents/navigation_controller.h" | 12 #include "chrome/browser/tab_contents/navigation_controller.h" |
| 13 #include "chrome/browser/tab_contents/navigation_entry.h" | 13 #include "chrome/browser/tab_contents/navigation_entry.h" |
| 14 #include "chrome/browser/tab_contents/web_contents.h" | 14 #include "chrome/browser/tab_contents/web_contents.h" |
| 15 #include "chrome/browser/tab_contents/web_contents_view_win.h" | 15 #include "chrome/browser/tab_contents/web_contents_view_win.h" |
| 16 #include "chrome/views/window.h" | 16 #include "chrome/views/window.h" |
| 17 #include "chrome/views/window_delegate.h" | 17 #include "chrome/views/window_delegate.h" |
| 18 #include "net/base/escape.h" | 18 #include "net/base/escape.h" |
| 19 | 19 |
| 20 enum ResourceRequestAction { |
| 21 BLOCK, |
| 22 RESUME, |
| 23 CANCEL |
| 24 }; |
| 25 |
| 20 namespace { | 26 namespace { |
| 21 | 27 |
| 22 class ResourceRequestTask : public Task { | 28 class ResourceRequestTask : public Task { |
| 23 public: | 29 public: |
| 24 ResourceRequestTask(RenderViewHost* render_view_host, | 30 ResourceRequestTask(int process_id, |
| 31 int render_view_host_id, |
| 25 ResourceRequestAction action) | 32 ResourceRequestAction action) |
| 26 : action_(action), | 33 : action_(action), |
| 27 process_id_(render_view_host->process()->host_id()), | 34 process_id_(process_id), |
| 28 render_view_host_id_(render_view_host->routing_id()), | 35 render_view_host_id_(render_view_host_id), |
| 29 resource_dispatcher_host_( | 36 resource_dispatcher_host_( |
| 30 g_browser_process->resource_dispatcher_host()) { | 37 g_browser_process->resource_dispatcher_host()) { |
| 31 } | 38 } |
| 32 | 39 |
| 33 virtual void Run() { | 40 virtual void Run() { |
| 34 switch (action_) { | 41 switch (action_) { |
| 35 case BLOCK: | 42 case BLOCK: |
| 36 resource_dispatcher_host_->BlockRequestsForRenderView( | 43 resource_dispatcher_host_->BlockRequestsForRenderView( |
| 37 process_id_, render_view_host_id_); | 44 process_id_, render_view_host_id_); |
| 38 break; | 45 break; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 65 InterstitialPage::tab_to_interstitial_page_ = NULL; | 72 InterstitialPage::tab_to_interstitial_page_ = NULL; |
| 66 | 73 |
| 67 InterstitialPage::InterstitialPage(WebContents* tab, | 74 InterstitialPage::InterstitialPage(WebContents* tab, |
| 68 bool new_navigation, | 75 bool new_navigation, |
| 69 const GURL& url) | 76 const GURL& url) |
| 70 : tab_(tab), | 77 : tab_(tab), |
| 71 url_(url), | 78 url_(url), |
| 72 action_taken_(false), | 79 action_taken_(false), |
| 73 enabled_(true), | 80 enabled_(true), |
| 74 new_navigation_(new_navigation), | 81 new_navigation_(new_navigation), |
| 82 original_rvh_process_id_(tab->render_view_host()->process()->host_id()), |
| 83 original_rvh_id_(tab->render_view_host()->routing_id()), |
| 75 render_view_host_(NULL), | 84 render_view_host_(NULL), |
| 85 resource_dispatcher_host_notified_(false), |
| 76 should_revert_tab_title_(false), | 86 should_revert_tab_title_(false), |
| 77 ui_loop_(MessageLoop::current()) { | 87 ui_loop_(MessageLoop::current()) { |
| 78 InitInterstitialPageMap(); | 88 InitInterstitialPageMap(); |
| 79 // It would be inconsistent to create an interstitial with no new navigation | 89 // It would be inconsistent to create an interstitial with no new navigation |
| 80 // (which is the case when the interstitial was triggered by a sub-resource on | 90 // (which is the case when the interstitial was triggered by a sub-resource on |
| 81 // a page) when we have a pending entry (in the process of loading a new top | 91 // a page) when we have a pending entry (in the process of loading a new top |
| 82 // frame). | 92 // frame). |
| 83 DCHECK(new_navigation || !tab->controller()->GetPendingEntry()); | 93 DCHECK(new_navigation || !tab->controller()->GetPendingEntry()); |
| 84 } | 94 } |
| 85 | 95 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); | 160 tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); |
| 151 } | 161 } |
| 152 delete this; | 162 delete this; |
| 153 } | 163 } |
| 154 | 164 |
| 155 void InterstitialPage::Observe(NotificationType type, | 165 void InterstitialPage::Observe(NotificationType type, |
| 156 const NotificationSource& source, | 166 const NotificationSource& source, |
| 157 const NotificationDetails& details) { | 167 const NotificationDetails& details) { |
| 158 switch (type) { | 168 switch (type) { |
| 159 case NOTIFY_NAV_ENTRY_PENDING: | 169 case NOTIFY_NAV_ENTRY_PENDING: |
| 160 // We are navigating away from the interstitial. Make sure clicking on | 170 // We are navigating away from the interstitial (the user has typed a URL |
| 161 // the interstitial will have no effect. | 171 // in the location bar or clicked a bookmark). Make sure clicking on the |
| 172 // interstitial will have no effect. Also cancel any blocked requests |
| 173 // on the ResourceDispatcherHost. Note that when we get this notification |
| 174 // the RenderViewHost has not yet navigated so we'll unblock the |
| 175 // RenderViewHost before the resource request for the new page we are |
| 176 // navigating arrives in the ResourceDispatcherHost. This ensures that |
| 177 // request won't be blocked if the same RenderViewHost was used for the |
| 178 // new navigation. |
| 162 Disable(); | 179 Disable(); |
| 180 DCHECK(!resource_dispatcher_host_notified_); |
| 181 TakeActionOnResourceDispatcher(CANCEL); |
| 163 break; | 182 break; |
| 164 case NOTIFY_RENDER_WIDGET_HOST_DESTROYED: | 183 case NOTIFY_RENDER_WIDGET_HOST_DESTROYED: |
| 165 if (!action_taken_) { | 184 if (!action_taken_) { |
| 166 // The RenderViewHost is being destroyed (as part of the tab being | 185 // The RenderViewHost is being destroyed (as part of the tab being |
| 167 // closed), make sure we clear the blocked requests. | 186 // closed), make sure we clear the blocked requests. |
| 168 DCHECK(Source<RenderViewHost>(source).ptr() == | 187 RenderViewHost* rvh = Source<RenderViewHost>(source).ptr(); |
| 169 tab_->render_view_host()); | 188 DCHECK(rvh->process()->host_id() == original_rvh_process_id_ && |
| 189 rvh->routing_id() == original_rvh_id_); |
| 170 TakeActionOnResourceDispatcher(CANCEL); | 190 TakeActionOnResourceDispatcher(CANCEL); |
| 171 } | 191 } |
| 172 break; | 192 break; |
| 173 case NOTIFY_TAB_CONTENTS_DESTROYED: | 193 case NOTIFY_TAB_CONTENTS_DESTROYED: |
| 174 case NOTIFY_NAV_ENTRY_COMMITTED: | 194 case NOTIFY_NAV_ENTRY_COMMITTED: |
| 175 if (!action_taken_) { | 195 if (!action_taken_) { |
| 176 // We are navigating away from the interstitial or closing a tab with an | 196 // We are navigating away from the interstitial or closing a tab with an |
| 177 // interstitial. Default to DontProceed(). We don't just call Hide as | 197 // interstitial. Default to DontProceed(). We don't just call Hide as |
| 178 // subclasses will almost certainly override DontProceed to do some work | 198 // subclasses will almost certainly override DontProceed to do some work |
| 179 // (ex: close pending connections). | 199 // (ex: close pending connections). |
| (...skipping 23 matching lines...) Expand all Loading... |
| 203 static_cast<WebContentsViewWin*>(tab_->view()); | 223 static_cast<WebContentsViewWin*>(tab_->view()); |
| 204 render_view_host->CreateRenderView(); | 224 render_view_host->CreateRenderView(); |
| 205 // SetSize must be called after CreateRenderView or the HWND won't show. | 225 // SetSize must be called after CreateRenderView or the HWND won't show. |
| 206 view->SetSize(web_contents_view->GetContainerSize()); | 226 view->SetSize(web_contents_view->GetContainerSize()); |
| 207 | 227 |
| 208 render_view_host->AllowDomAutomationBindings(); | 228 render_view_host->AllowDomAutomationBindings(); |
| 209 return render_view_host; | 229 return render_view_host; |
| 210 } | 230 } |
| 211 | 231 |
| 212 void InterstitialPage::Proceed() { | 232 void InterstitialPage::Proceed() { |
| 213 DCHECK(!action_taken_); | 233 if (action_taken_) { |
| 234 NOTREACHED(); |
| 235 return; |
| 236 } |
| 214 Disable(); | 237 Disable(); |
| 215 action_taken_ = true; | 238 action_taken_ = true; |
| 216 | 239 |
| 217 // Resumes the throbber. | 240 // Resumes the throbber. |
| 218 tab_->SetIsLoading(true, NULL); | 241 tab_->SetIsLoading(true, NULL); |
| 219 | 242 |
| 220 // If this is a new navigation, the old page is going away, so we cancel any | 243 // If this is a new navigation, the old page is going away, so we cancel any |
| 221 // blocked requests for it. If it is not a new navigation, then it means the | 244 // blocked requests for it. If it is not a new navigation, then it means the |
| 222 // interstitial was shown as a result of a resource loading in the page. | 245 // interstitial was shown as a result of a resource loading in the page. |
| 223 // Since the user wants to proceed, we'll let any blocked request go through. | 246 // Since the user wants to proceed, we'll let any blocked request go through. |
| 224 if (new_navigation_) | 247 if (new_navigation_) |
| 225 TakeActionOnResourceDispatcher(CANCEL); | 248 TakeActionOnResourceDispatcher(CANCEL); |
| 226 else | 249 else |
| 227 TakeActionOnResourceDispatcher(RESUME); | 250 TakeActionOnResourceDispatcher(RESUME); |
| 228 | 251 |
| 229 // No need to hide if we are a new navigation, we'll get hidden when the | 252 // No need to hide if we are a new navigation, we'll get hidden when the |
| 230 // navigation is committed. | 253 // navigation is committed. |
| 231 if (!new_navigation_) { | 254 if (!new_navigation_) { |
| 232 Hide(); | 255 Hide(); |
| 233 // WARNING: we are now deleted! | 256 // WARNING: we are now deleted! |
| 234 } | 257 } |
| 235 } | 258 } |
| 236 | 259 |
| 237 void InterstitialPage::DontProceed() { | 260 void InterstitialPage::DontProceed() { |
| 238 DCHECK(!action_taken_); | 261 if (action_taken_) { |
| 262 NOTREACHED(); |
| 263 return; |
| 264 } |
| 239 Disable(); | 265 Disable(); |
| 240 action_taken_ = true; | 266 action_taken_ = true; |
| 241 | 267 |
| 242 // If this is a new navigation, we are returning to the original page, so we | 268 // If this is a new navigation, we are returning to the original page, so we |
| 243 // resume blocked requests for it. If it is not a new navigation, then it | 269 // resume blocked requests for it. If it is not a new navigation, then it |
| 244 // means the interstitial was shown as a result of a resource loading in the | 270 // means the interstitial was shown as a result of a resource loading in the |
| 245 // page and we won't return to the original page, so we cancel blocked | 271 // page and we won't return to the original page, so we cancel blocked |
| 246 // requests in that case. | 272 // requests in that case. |
| 247 if (new_navigation_) | 273 if (new_navigation_) |
| 248 TakeActionOnResourceDispatcher(RESUME); | 274 TakeActionOnResourceDispatcher(RESUME); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 } | 345 } |
| 320 | 346 |
| 321 void InterstitialPage::Disable() { | 347 void InterstitialPage::Disable() { |
| 322 enabled_ = false; | 348 enabled_ = false; |
| 323 } | 349 } |
| 324 | 350 |
| 325 void InterstitialPage::TakeActionOnResourceDispatcher( | 351 void InterstitialPage::TakeActionOnResourceDispatcher( |
| 326 ResourceRequestAction action) { | 352 ResourceRequestAction action) { |
| 327 DCHECK(MessageLoop::current() == ui_loop_) << | 353 DCHECK(MessageLoop::current() == ui_loop_) << |
| 328 "TakeActionOnResourceDispatcher should be called on the main thread."; | 354 "TakeActionOnResourceDispatcher should be called on the main thread."; |
| 355 |
| 356 if (action == CANCEL || action == RESUME) { |
| 357 if (resource_dispatcher_host_notified_) |
| 358 return; |
| 359 resource_dispatcher_host_notified_ = true; |
| 360 } |
| 361 |
| 329 // The tab might not have a render_view_host if it was closed (in which case, | 362 // The tab might not have a render_view_host if it was closed (in which case, |
| 330 // we have taken care of the blocked requests when processing | 363 // we have taken care of the blocked requests when processing |
| 331 // NOTIFY_RENDER_WIDGET_HOST_DESTROYED. | 364 // NOTIFY_RENDER_WIDGET_HOST_DESTROYED. |
| 332 // Also we need to test there is an IO thread, as when unit-tests we don't | 365 // Also we need to test there is an IO thread, as when unit-tests we don't |
| 333 // have one. | 366 // have one. |
| 334 if (tab_->render_view_host() && g_browser_process->io_thread()) { | 367 RenderViewHost* rvh = RenderViewHost::FromID(original_rvh_process_id_, |
| 368 original_rvh_id_); |
| 369 if (rvh && g_browser_process->io_thread()) { |
| 335 g_browser_process->io_thread()->message_loop()->PostTask( | 370 g_browser_process->io_thread()->message_loop()->PostTask( |
| 336 FROM_HERE, new ResourceRequestTask(tab_->render_view_host(), action)); | 371 FROM_HERE, new ResourceRequestTask(original_rvh_process_id_, |
| 372 original_rvh_id_, |
| 373 action)); |
| 337 } | 374 } |
| 338 } | 375 } |
| 339 | 376 |
| 340 // static | 377 // static |
| 341 void InterstitialPage::InitInterstitialPageMap() { | 378 void InterstitialPage::InitInterstitialPageMap() { |
| 342 if (!tab_to_interstitial_page_) | 379 if (!tab_to_interstitial_page_) |
| 343 tab_to_interstitial_page_ = new InterstitialPageMap; | 380 tab_to_interstitial_page_ = new InterstitialPageMap; |
| 344 } | 381 } |
| 345 | 382 |
| 346 // static | 383 // static |
| 347 InterstitialPage* InterstitialPage::GetInterstitialPage( | 384 InterstitialPage* InterstitialPage::GetInterstitialPage( |
| 348 WebContents* web_contents) { | 385 WebContents* web_contents) { |
| 349 InitInterstitialPageMap(); | 386 InitInterstitialPageMap(); |
| 350 InterstitialPageMap::const_iterator iter = | 387 InterstitialPageMap::const_iterator iter = |
| 351 tab_to_interstitial_page_->find(web_contents); | 388 tab_to_interstitial_page_->find(web_contents); |
| 352 if (iter == tab_to_interstitial_page_->end()) | 389 if (iter == tab_to_interstitial_page_->end()) |
| 353 return NULL; | 390 return NULL; |
| 354 | 391 |
| 355 return iter->second; | 392 return iter->second; |
| 356 } | 393 } |
| 394 |
| OLD | NEW |