| Index: chrome/browser/interstitial_page.cc
|
| ===================================================================
|
| --- chrome/browser/interstitial_page.cc (revision 7403)
|
| +++ chrome/browser/interstitial_page.cc (working copy)
|
| @@ -17,6 +17,55 @@
|
| #include "chrome/views/window_delegate.h"
|
| #include "net/base/escape.h"
|
|
|
| +enum ResourceRequestAction {
|
| + BLOCK,
|
| + RESUME,
|
| + CANCEL
|
| +};
|
| +
|
| +namespace {
|
| +
|
| +class ResourceRequestTask : public Task {
|
| + public:
|
| + ResourceRequestTask(RenderViewHost* render_view_host,
|
| + ResourceRequestAction action)
|
| + : action_(action),
|
| + process_id_(render_view_host->process()->host_id()),
|
| + render_view_host_id_(render_view_host->routing_id()),
|
| + resource_dispatcher_host_(
|
| + g_browser_process->resource_dispatcher_host()) {
|
| + }
|
| +
|
| + virtual void Run() {
|
| + switch (action_) {
|
| + case BLOCK:
|
| + resource_dispatcher_host_->BlockRequestsForRenderView(
|
| + process_id_, render_view_host_id_);
|
| + break;
|
| + case RESUME:
|
| + resource_dispatcher_host_->ResumeBlockedRequestsForRenderView(
|
| + process_id_, render_view_host_id_);
|
| + break;
|
| + case CANCEL:
|
| + resource_dispatcher_host_->CancelBlockedRequestsForRenderView(
|
| + process_id_, render_view_host_id_);
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + }
|
| +
|
| + private:
|
| + ResourceRequestAction action_;
|
| + int process_id_;
|
| + int render_view_host_id_;
|
| + ResourceDispatcherHost* resource_dispatcher_host_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ResourceRequestTask);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| // static
|
| InterstitialPage::InterstitialPageMap*
|
| InterstitialPage::tab_to_interstitial_page_ = NULL;
|
| @@ -30,7 +79,8 @@
|
| enabled_(true),
|
| new_navigation_(new_navigation),
|
| render_view_host_(NULL),
|
| - should_revert_tab_title_(false) {
|
| + should_revert_tab_title_(false),
|
| + ui_loop_(MessageLoop::current()) {
|
| InitInterstitialPageMap();
|
| // It would be inconsistent to create an interstitial with no new navigation
|
| // (which is the case when the interstitial was triggered by a sub-resource on
|
| @@ -51,6 +101,16 @@
|
| if (tab_->interstitial_page())
|
| tab_->interstitial_page()->DontProceed();
|
|
|
| + // Block the resource requests for the render view host while it is hidden.
|
| + TakeActionOnResourceDispatcher(BLOCK);
|
| + // We need to be notified when the RenderViewHost is destroyed so we can
|
| + // cancel the blocked requests. We cannot do that on
|
| + // NOTIFY_TAB_CONTENTS_DESTROYED as at that point the RenderViewHost has
|
| + // already been destroyed.
|
| + notification_registrar_.Add(
|
| + this, NOTIFY_RENDER_WIDGET_HOST_DESTROYED,
|
| + Source<RenderWidgetHost>(tab_->render_view_host()));
|
| +
|
| // Update the tab_to_interstitial_page_ map.
|
| InterstitialPageMap::const_iterator iter =
|
| tab_to_interstitial_page_->find(tab_);
|
| @@ -101,26 +161,36 @@
|
| void InterstitialPage::Observe(NotificationType type,
|
| const NotificationSource& source,
|
| const NotificationDetails& details) {
|
| - if (type == NOTIFY_NAV_ENTRY_PENDING) {
|
| - // We are navigating away from the interstitial. Make sure clicking on the
|
| - // interstitial will have no effect.
|
| - Disable();
|
| - return;
|
| + switch (type) {
|
| + case NOTIFY_NAV_ENTRY_PENDING:
|
| + // We are navigating away from the interstitial. Make sure clicking on
|
| + // the interstitial will have no effect.
|
| + Disable();
|
| + break;
|
| + case NOTIFY_RENDER_WIDGET_HOST_DESTROYED:
|
| + // The RenderViewHost is being destroyed (as part of the tab being closed)
|
| + // make sure we clear the blocked requests.
|
| + DCHECK(Source<RenderViewHost>(source).ptr() == tab_->render_view_host());
|
| + TakeActionOnResourceDispatcher(CANCEL);
|
| + break;
|
| + case NOTIFY_TAB_CONTENTS_DESTROYED:
|
| + case NOTIFY_NAV_ENTRY_COMMITTED:
|
| + if (!action_taken_) {
|
| + // We are navigating away from the interstitial or closing a tab with an
|
| + // interstitial. Default to DontProceed(). We don't just call Hide as
|
| + // subclasses will almost certainly override DontProceed to do some work
|
| + // (ex: close pending connections).
|
| + DontProceed();
|
| + } else {
|
| + // User decided to proceed and either the navigation was committed or
|
| + // the tab was closed before that.
|
| + Hide();
|
| + // WARNING: we are now deleted!
|
| + }
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| }
|
| - DCHECK(type == NOTIFY_TAB_CONTENTS_DESTROYED ||
|
| - type == NOTIFY_NAV_ENTRY_COMMITTED);
|
| - if (!action_taken_) {
|
| - // We are navigating away from the interstitial or closing a tab with an
|
| - // interstitial. Default to DontProceed(). We don't just call Hide as
|
| - // subclasses will almost certainly override DontProceed to do some work
|
| - // (ex: close pending connections).
|
| - DontProceed();
|
| - } else {
|
| - // User decided to proceed and either the navigation was committed or the
|
| - // tab was closed before that.
|
| - Hide();
|
| - // WARNING: we are now deleted!
|
| - }
|
| }
|
|
|
| RenderViewHost* InterstitialPage::CreateRenderViewHost() {
|
| @@ -150,6 +220,15 @@
|
| // Resumes the throbber.
|
| tab_->SetIsLoading(true, NULL);
|
|
|
| + // If this is a new navigation, the old page is going away, so we cancel any
|
| + // blocked requests for it. If it is not a new navigation, then it means the
|
| + // interstitial was shown as a result of a resource loading in the page.
|
| + // Since the user wants to proceed, we'll let any blocked request go through.
|
| + if (new_navigation_)
|
| + TakeActionOnResourceDispatcher(CANCEL);
|
| + else
|
| + TakeActionOnResourceDispatcher(RESUME);
|
| +
|
| // No need to hide if we are a new navigation, we'll get hidden when the
|
| // navigation is committed.
|
| if (!new_navigation_) {
|
| @@ -163,6 +242,16 @@
|
| Disable();
|
| action_taken_ = true;
|
|
|
| + // If this is a new navigation, we are returning to the original page, so we
|
| + // resume blocked requests for it. If it is not a new navigation, then it
|
| + // means the interstitial was shown as a result of a resource loading in the
|
| + // page and we won't return to the original page, so we cancel blocked
|
| + // requests in that case.
|
| + if (new_navigation_)
|
| + TakeActionOnResourceDispatcher(RESUME);
|
| + else
|
| + TakeActionOnResourceDispatcher(CANCEL);
|
| +
|
| if (new_navigation_) {
|
| // Since no navigation happens we have to discard the transient entry
|
| // explicitely. Note that by calling DiscardNonCommittedEntries() we also
|
| @@ -236,6 +325,21 @@
|
| enabled_ = false;
|
| }
|
|
|
| +void InterstitialPage::TakeActionOnResourceDispatcher(
|
| + ResourceRequestAction action) {
|
| + DCHECK(MessageLoop::current() == ui_loop_) <<
|
| + "TakeActionOnResourceDispatcher should be called on the main thread.";
|
| + // The tab might not have a render_view_host if it was closed (in which case,
|
| + // we have taken care of the blocked requests when processing
|
| + // NOTIFY_RENDER_WIDGET_HOST_DESTROYED.
|
| + // Also we need to test there is an IO thread, as when unit-tests we don't
|
| + // have one.
|
| + if (tab_->render_view_host() && g_browser_process->io_thread()) {
|
| + g_browser_process->io_thread()->message_loop()->PostTask(
|
| + FROM_HERE, new ResourceRequestTask(tab_->render_view_host(), action));
|
| + }
|
| +}
|
| +
|
| // static
|
| void InterstitialPage::InitInterstitialPageMap() {
|
| if (!tab_to_interstitial_page_)
|
|
|