Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(562)

Side by Side Diff: chrome/browser/interstitial_page.cc

Issue 16546: Blocking resource request for hidden page when interstitial showing (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/interstitial_page.h" 5 #include "chrome/browser/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/navigation_controller.h" 11 #include "chrome/browser/navigation_controller.h"
12 #include "chrome/browser/navigation_entry.h" 12 #include "chrome/browser/navigation_entry.h"
13 #include "chrome/browser/render_widget_host_view_win.h" 13 #include "chrome/browser/render_widget_host_view_win.h"
14 #include "chrome/browser/web_contents.h" 14 #include "chrome/browser/web_contents.h"
15 #include "chrome/browser/web_contents_view_win.h" 15 #include "chrome/browser/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
26 namespace {
27
28 class ResourceRequestTask : public Task {
29 public:
30 ResourceRequestTask(RenderViewHost* render_view_host,
31 ResourceRequestAction action)
32 : action_(action),
33 process_id_(render_view_host->process()->host_id()),
34 render_view_host_id_(render_view_host->routing_id()),
35 resource_dispatcher_host_(
36 g_browser_process->resource_dispatcher_host()) {
37 }
38
39 virtual void Run() {
40 switch (action_) {
41 case BLOCK:
42 resource_dispatcher_host_->BlockRequestsForRenderView(
43 process_id_, render_view_host_id_);
44 break;
45 case RESUME:
46 resource_dispatcher_host_->ResumeBlockedRequestsForRenderView(
47 process_id_, render_view_host_id_);
48 break;
49 case CANCEL:
50 resource_dispatcher_host_->CancelBlockedRequestsForRenderView(
51 process_id_, render_view_host_id_);
52 break;
53 default:
54 NOTREACHED();
55 }
56 }
57
58 private:
59 ResourceRequestAction action_;
60 int process_id_;
61 int render_view_host_id_;
62 ResourceDispatcherHost* resource_dispatcher_host_;
63
64 DISALLOW_COPY_AND_ASSIGN(ResourceRequestTask);
65 };
66
67 } // namespace
68
20 // static 69 // static
21 InterstitialPage::InterstitialPageMap* 70 InterstitialPage::InterstitialPageMap*
22 InterstitialPage::tab_to_interstitial_page_ = NULL; 71 InterstitialPage::tab_to_interstitial_page_ = NULL;
23 72
24 InterstitialPage::InterstitialPage(WebContents* tab, 73 InterstitialPage::InterstitialPage(WebContents* tab,
25 bool new_navigation, 74 bool new_navigation,
26 const GURL& url) 75 const GURL& url)
27 : tab_(tab), 76 : tab_(tab),
28 url_(url), 77 url_(url),
29 action_taken_(false), 78 action_taken_(false),
30 enabled_(true), 79 enabled_(true),
31 new_navigation_(new_navigation), 80 new_navigation_(new_navigation),
32 render_view_host_(NULL), 81 render_view_host_(NULL),
33 should_revert_tab_title_(false) { 82 should_revert_tab_title_(false),
83 ui_loop_(MessageLoop::current()) {
34 InitInterstitialPageMap(); 84 InitInterstitialPageMap();
35 // It would be inconsistent to create an interstitial with no new navigation 85 // It would be inconsistent to create an interstitial with no new navigation
36 // (which is the case when the interstitial was triggered by a sub-resource on 86 // (which is the case when the interstitial was triggered by a sub-resource on
37 // a page) when we have a pending entry (in the process of loading a new top 87 // a page) when we have a pending entry (in the process of loading a new top
38 // frame). 88 // frame).
39 DCHECK(new_navigation || !tab->controller()->GetPendingEntry()); 89 DCHECK(new_navigation || !tab->controller()->GetPendingEntry());
40 } 90 }
41 91
42 InterstitialPage::~InterstitialPage() { 92 InterstitialPage::~InterstitialPage() {
43 InterstitialPageMap::iterator iter = tab_to_interstitial_page_->find(tab_); 93 InterstitialPageMap::iterator iter = tab_to_interstitial_page_->find(tab_);
44 DCHECK(iter != tab_to_interstitial_page_->end()); 94 DCHECK(iter != tab_to_interstitial_page_->end());
45 tab_to_interstitial_page_->erase(iter); 95 tab_to_interstitial_page_->erase(iter);
46 DCHECK(!render_view_host_); 96 DCHECK(!render_view_host_);
47 } 97 }
48 98
49 void InterstitialPage::Show() { 99 void InterstitialPage::Show() {
50 // If an interstitial is already showing, close it before showing the new one. 100 // If an interstitial is already showing, close it before showing the new one.
51 if (tab_->interstitial_page()) 101 if (tab_->interstitial_page())
52 tab_->interstitial_page()->DontProceed(); 102 tab_->interstitial_page()->DontProceed();
53 103
104 // Block the resource requests for the render view host while it is hidden.
105 TakeActionOnResourceDispatcher(BLOCK);
106 // We need to be notified when the RenderViewHost is destroyed so we can
107 // cancel the blocked requests. We cannot do that on
108 // NOTIFY_TAB_CONTENTS_DESTROYED as at that point the RenderViewHost has
109 // already been destroyed.
110 notification_registrar_.Add(
111 this, NOTIFY_RENDER_WIDGET_HOST_DESTROYED,
112 Source<RenderWidgetHost>(tab_->render_view_host()));
113
54 // Update the tab_to_interstitial_page_ map. 114 // Update the tab_to_interstitial_page_ map.
55 InterstitialPageMap::const_iterator iter = 115 InterstitialPageMap::const_iterator iter =
56 tab_to_interstitial_page_->find(tab_); 116 tab_to_interstitial_page_->find(tab_);
57 DCHECK(iter == tab_to_interstitial_page_->end()); 117 DCHECK(iter == tab_to_interstitial_page_->end());
58 (*tab_to_interstitial_page_)[tab_] = this; 118 (*tab_to_interstitial_page_)[tab_] = this;
59 119
60 if (new_navigation_) { 120 if (new_navigation_) {
61 NavigationEntry* entry = new NavigationEntry(TAB_CONTENTS_WEB); 121 NavigationEntry* entry = new NavigationEntry(TAB_CONTENTS_WEB);
62 entry->set_url(url_); 122 entry->set_url(url_);
63 entry->set_display_url(url_); 123 entry->set_display_url(url_);
(...skipping 30 matching lines...) Expand all
94 if (!new_navigation_ && should_revert_tab_title_) { 154 if (!new_navigation_ && should_revert_tab_title_) {
95 entry->set_title(original_tab_title_); 155 entry->set_title(original_tab_title_);
96 tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); 156 tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE);
97 } 157 }
98 delete this; 158 delete this;
99 } 159 }
100 160
101 void InterstitialPage::Observe(NotificationType type, 161 void InterstitialPage::Observe(NotificationType type,
102 const NotificationSource& source, 162 const NotificationSource& source,
103 const NotificationDetails& details) { 163 const NotificationDetails& details) {
104 if (type == NOTIFY_NAV_ENTRY_PENDING) { 164 switch (type) {
105 // We are navigating away from the interstitial. Make sure clicking on the 165 case NOTIFY_NAV_ENTRY_PENDING:
106 // interstitial will have no effect. 166 // We are navigating away from the interstitial. Make sure clicking on
107 Disable(); 167 // the interstitial will have no effect.
108 return; 168 Disable();
109 } 169 break;
110 DCHECK(type == NOTIFY_TAB_CONTENTS_DESTROYED || 170 case NOTIFY_RENDER_WIDGET_HOST_DESTROYED:
111 type == NOTIFY_NAV_ENTRY_COMMITTED); 171 // The RenderViewHost is being destroyed (as part of the tab being closed)
112 if (!action_taken_) { 172 // make sure we clear the blocked requests.
113 // We are navigating away from the interstitial or closing a tab with an 173 DCHECK(Source<RenderViewHost>(source).ptr() == tab_->render_view_host());
114 // interstitial. Default to DontProceed(). We don't just call Hide as 174 TakeActionOnResourceDispatcher(CANCEL);
115 // subclasses will almost certainly override DontProceed to do some work 175 break;
116 // (ex: close pending connections). 176 case NOTIFY_TAB_CONTENTS_DESTROYED:
117 DontProceed(); 177 case NOTIFY_NAV_ENTRY_COMMITTED:
118 } else { 178 if (!action_taken_) {
119 // User decided to proceed and either the navigation was committed or the 179 // We are navigating away from the interstitial or closing a tab with an
120 // tab was closed before that. 180 // interstitial. Default to DontProceed(). We don't just call Hide as
121 Hide(); 181 // subclasses will almost certainly override DontProceed to do some work
122 // WARNING: we are now deleted! 182 // (ex: close pending connections).
183 DontProceed();
184 } else {
185 // User decided to proceed and either the navigation was committed or
186 // the tab was closed before that.
187 Hide();
188 // WARNING: we are now deleted!
189 }
190 break;
191 default:
192 NOTREACHED();
123 } 193 }
124 } 194 }
125 195
126 RenderViewHost* InterstitialPage::CreateRenderViewHost() { 196 RenderViewHost* InterstitialPage::CreateRenderViewHost() {
127 RenderViewHost* render_view_host = new RenderViewHost( 197 RenderViewHost* render_view_host = new RenderViewHost(
128 SiteInstance::CreateSiteInstance(tab()->profile()), 198 SiteInstance::CreateSiteInstance(tab()->profile()),
129 this, MSG_ROUTING_NONE, NULL); 199 this, MSG_ROUTING_NONE, NULL);
130 RenderWidgetHostViewWin* view = 200 RenderWidgetHostViewWin* view =
131 new RenderWidgetHostViewWin(render_view_host); 201 new RenderWidgetHostViewWin(render_view_host);
132 render_view_host->set_view(view); 202 render_view_host->set_view(view);
(...skipping 10 matching lines...) Expand all
143 } 213 }
144 214
145 void InterstitialPage::Proceed() { 215 void InterstitialPage::Proceed() {
146 DCHECK(!action_taken_); 216 DCHECK(!action_taken_);
147 Disable(); 217 Disable();
148 action_taken_ = true; 218 action_taken_ = true;
149 219
150 // Resumes the throbber. 220 // Resumes the throbber.
151 tab_->SetIsLoading(true, NULL); 221 tab_->SetIsLoading(true, NULL);
152 222
223 // If this is a new navigation, the old page is going away, so we cancel any
224 // blocked requests for it. If it is not a new navigation, then it means the
225 // interstitial was shown as a result of a resource loading in the page.
226 // Since the user wants to proceed, we'll let any blocked request go through.
227 if (new_navigation_)
228 TakeActionOnResourceDispatcher(CANCEL);
229 else
230 TakeActionOnResourceDispatcher(RESUME);
231
153 // No need to hide if we are a new navigation, we'll get hidden when the 232 // No need to hide if we are a new navigation, we'll get hidden when the
154 // navigation is committed. 233 // navigation is committed.
155 if (!new_navigation_) { 234 if (!new_navigation_) {
156 Hide(); 235 Hide();
157 // WARNING: we are now deleted! 236 // WARNING: we are now deleted!
158 } 237 }
159 } 238 }
160 239
161 void InterstitialPage::DontProceed() { 240 void InterstitialPage::DontProceed() {
162 DCHECK(!action_taken_); 241 DCHECK(!action_taken_);
163 Disable(); 242 Disable();
164 action_taken_ = true; 243 action_taken_ = true;
165 244
245 // If this is a new navigation, we are returning to the original page, so we
246 // resume blocked requests for it. If it is not a new navigation, then it
247 // means the interstitial was shown as a result of a resource loading in the
248 // page and we won't return to the original page, so we cancel blocked
249 // requests in that case.
250 if (new_navigation_)
251 TakeActionOnResourceDispatcher(RESUME);
252 else
253 TakeActionOnResourceDispatcher(CANCEL);
254
166 if (new_navigation_) { 255 if (new_navigation_) {
167 // Since no navigation happens we have to discard the transient entry 256 // Since no navigation happens we have to discard the transient entry
168 // explicitely. Note that by calling DiscardNonCommittedEntries() we also 257 // explicitely. Note that by calling DiscardNonCommittedEntries() we also
169 // discard the pending entry, which is what we want, since the navigation is 258 // discard the pending entry, which is what we want, since the navigation is
170 // cancelled. 259 // cancelled.
171 tab_->controller()->DiscardNonCommittedEntries(); 260 tab_->controller()->DiscardNonCommittedEntries();
172 } 261 }
173 262
174 Hide(); 263 Hide();
175 // WARNING: we are now deleted! 264 // WARNING: we are now deleted!
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 should_revert_tab_title_ = true; 318 should_revert_tab_title_ = true;
230 } 319 }
231 entry->set_title(title); 320 entry->set_title(title);
232 tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE); 321 tab_->NotifyNavigationStateChanged(TabContents::INVALIDATE_TITLE);
233 } 322 }
234 323
235 void InterstitialPage::Disable() { 324 void InterstitialPage::Disable() {
236 enabled_ = false; 325 enabled_ = false;
237 } 326 }
238 327
328 void InterstitialPage::TakeActionOnResourceDispatcher(
329 ResourceRequestAction action) {
330 DCHECK(MessageLoop::current() == ui_loop_) <<
331 "TakeActionOnResourceDispatcher should be called on the main thread.";
332 // The tab might not have a render_view_host if it was closed (in which case,
333 // we have taken care of the blocked requests when processing
334 // NOTIFY_RENDER_WIDGET_HOST_DESTROYED.
335 // Also we need to test there is an IO thread, as when unit-tests we don't
336 // have one.
337 if (tab_->render_view_host() && g_browser_process->io_thread()) {
338 g_browser_process->io_thread()->message_loop()->PostTask(
339 FROM_HERE, new ResourceRequestTask(tab_->render_view_host(), action));
340 }
341 }
342
239 // static 343 // static
240 void InterstitialPage::InitInterstitialPageMap() { 344 void InterstitialPage::InitInterstitialPageMap() {
241 if (!tab_to_interstitial_page_) 345 if (!tab_to_interstitial_page_)
242 tab_to_interstitial_page_ = new InterstitialPageMap; 346 tab_to_interstitial_page_ = new InterstitialPageMap;
243 } 347 }
244 348
245 // static 349 // static
246 InterstitialPage* InterstitialPage::GetInterstitialPage( 350 InterstitialPage* InterstitialPage::GetInterstitialPage(
247 WebContents* web_contents) { 351 WebContents* web_contents) {
248 InitInterstitialPageMap(); 352 InitInterstitialPageMap();
249 InterstitialPageMap::const_iterator iter = 353 InterstitialPageMap::const_iterator iter =
250 tab_to_interstitial_page_->find(web_contents); 354 tab_to_interstitial_page_->find(web_contents);
251 if (iter == tab_to_interstitial_page_->end()) 355 if (iter == tab_to_interstitial_page_->end())
252 return NULL; 356 return NULL;
253 357
254 return iter->second; 358 return iter->second;
255 } 359 }
OLDNEW
« no previous file with comments | « chrome/browser/interstitial_page.h ('k') | chrome/browser/renderer_host/resource_dispatcher_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698