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

Side by Side Diff: chrome/browser/download/download_request_limiter.cc

Issue 10412061: Fix crashes in DownloadRequestLimiter when extension popups/bubbles initiate downloads automatically (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: test Created 8 years, 7 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) 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 "chrome/browser/download/download_request_limiter.h" 5 #include "chrome/browser/download/download_request_limiter.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "chrome/browser/download/download_request_infobar_delegate.h" 9 #include "chrome/browser/download/download_request_infobar_delegate.h"
10 #include "chrome/browser/infobars/infobar_tab_helper.h" 10 #include "chrome/browser/infobars/infobar_tab_helper.h"
(...skipping 11 matching lines...) Expand all
22 22
23 using content::BrowserThread; 23 using content::BrowserThread;
24 using content::NavigationController; 24 using content::NavigationController;
25 using content::NavigationEntry; 25 using content::NavigationEntry;
26 using content::WebContents; 26 using content::WebContents;
27 27
28 // TabDownloadState ------------------------------------------------------------ 28 // TabDownloadState ------------------------------------------------------------
29 29
30 DownloadRequestLimiter::TabDownloadState::TabDownloadState( 30 DownloadRequestLimiter::TabDownloadState::TabDownloadState(
31 DownloadRequestLimiter* host, 31 DownloadRequestLimiter* host,
32 NavigationController* controller, 32 WebContents* contents,
33 NavigationController* originating_controller) 33 WebContents* originating_web_contents)
34 : host_(host), 34 : content::WebContentsObserver(contents),
35 controller_(controller), 35 host_(host),
36 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD), 36 status_(DownloadRequestLimiter::ALLOW_ONE_DOWNLOAD),
37 download_count_(0), 37 download_count_(0),
38 infobar_(NULL) { 38 infobar_(NULL) {
39 content::Source<NavigationController> notification_source(controller); 39 content::Source<NavigationController> notification_source(
40 content::Source<content::WebContents> web_contents_source( 40 &contents->GetController());
41 controller->GetWebContents()); 41 content::Source<content::WebContents> web_contents_source(contents);
42 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 42 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
43 notification_source); 43 notification_source);
44 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 44 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
45 web_contents_source); 45 web_contents_source);
46 46
47 NavigationEntry* active_entry = originating_controller ? 47 NavigationEntry* active_entry = originating_web_contents ?
48 originating_controller->GetActiveEntry() : controller->GetActiveEntry(); 48 originating_web_contents->GetController().GetActiveEntry() :
49 contents->GetController().GetActiveEntry();
49 if (active_entry) 50 if (active_entry)
50 initial_page_host_ = active_entry->GetURL().host(); 51 initial_page_host_ = active_entry->GetURL().host();
51 } 52 }
52 53
53 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() { 54 DownloadRequestLimiter::TabDownloadState::~TabDownloadState() {
54 // We should only be destroyed after the callbacks have been notified. 55 // We should only be destroyed after the callbacks have been notified.
55 DCHECK(callbacks_.empty()); 56 DCHECK(callbacks_.empty());
56 57
57 // And we should have closed the infobar. 58 // And we should have closed the infobar.
58 DCHECK(!infobar_); 59 DCHECK(!infobar_);
59 } 60 }
60 61
61 void DownloadRequestLimiter::TabDownloadState::OnUserGesture() { 62 void DownloadRequestLimiter::TabDownloadState::DidGetUserGesture() {
62 if (is_showing_prompt()) { 63 if (is_showing_prompt()) {
63 // Don't change the state if the user clicks on the page some where. 64 // Don't change the state if the user clicks on the page some where.
64 return; 65 return;
65 } 66 }
66 67
67 if (status_ != DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS && 68 if (status_ != DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS &&
68 status_ != DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) { 69 status_ != DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) {
69 // Revert to default status. 70 // Revert to default status.
70 host_->Remove(this); 71 host_->Remove(this);
71 // WARNING: We've been deleted. 72 // WARNING: We've been deleted.
72 return; 73 return;
73 } 74 }
74 } 75 }
75 76
76 void DownloadRequestLimiter::TabDownloadState::PromptUserForDownload( 77 void DownloadRequestLimiter::TabDownloadState::PromptUserForDownload(
77 WebContents* tab, 78 WebContents* web_contents,
78 const DownloadRequestLimiter::Callback& callback) { 79 const DownloadRequestLimiter::Callback& callback) {
79 callbacks_.push_back(callback); 80 callbacks_.push_back(callback);
80 81
81 if (is_showing_prompt()) 82 if (is_showing_prompt())
82 return; // Already showing prompt. 83 return; // Already showing prompt.
83 84
84 if (DownloadRequestLimiter::delegate_) { 85 if (DownloadRequestLimiter::delegate_) {
85 NotifyCallbacks(DownloadRequestLimiter::delegate_->ShouldAllowDownload()); 86 NotifyCallbacks(DownloadRequestLimiter::delegate_->ShouldAllowDownload());
86 } else { 87 return;
87 InfoBarTabHelper* infobar_helper =
88 TabContentsWrapper::GetCurrentWrapperForContents(tab)->
89 infobar_tab_helper();
90 infobar_ = new DownloadRequestInfoBarDelegate(infobar_helper, this);
91 infobar_helper->AddInfoBar(infobar_);
92 } 88 }
89 TabContentsWrapper* tab_wrapper =
90 TabContentsWrapper::GetCurrentWrapperForContents(web_contents);
91 if (!tab_wrapper) {
92 // If |web_contents| doesn't have a tab_wrapper, then it isn't what a user
93 // thinks of as a tab, it's actually a "raw" WebContents like those used
94 // for extension popups/bubbles and hosted apps etc.
95 // TODO(benjhayden): If this is an automatic download from an extension,
96 // it would be convenient for the extension author if we send a message to
97 // the extension's DevTools console (as we do for CSP) about how
98 // extensions should use chrome.downloads.download() (requires the
99 // "downloads" permission) to automatically download >1 files.
100 Cancel();
101 return;
102 }
103 InfoBarTabHelper* infobar_helper = tab_wrapper->infobar_tab_helper();
104 infobar_ = new DownloadRequestInfoBarDelegate(infobar_helper, this);
105 infobar_helper->AddInfoBar(infobar_);
93 } 106 }
94 107
95 void DownloadRequestLimiter::TabDownloadState::Cancel() { 108 void DownloadRequestLimiter::TabDownloadState::Cancel() {
96 NotifyCallbacks(false); 109 NotifyCallbacks(false);
97 } 110 }
98 111
99 void DownloadRequestLimiter::TabDownloadState::Accept() { 112 void DownloadRequestLimiter::TabDownloadState::Accept() {
100 NotifyCallbacks(true); 113 NotifyCallbacks(true);
101 } 114 }
102 115
103 void DownloadRequestLimiter::TabDownloadState::Observe( 116 void DownloadRequestLimiter::TabDownloadState::Observe(
104 int type, 117 int type,
105 const content::NotificationSource& source, 118 const content::NotificationSource& source,
106 const content::NotificationDetails& details) { 119 const content::NotificationDetails& details) {
107 if (type != content::NOTIFICATION_NAV_ENTRY_PENDING && 120 if (type != content::NOTIFICATION_NAV_ENTRY_PENDING &&
108 type != content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { 121 type != content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
109 NOTREACHED(); 122 NOTREACHED();
110 return; 123 return;
111 } 124 }
125 content::NavigationController* controller = &web_contents()->GetController();
112 if (type == content::NOTIFICATION_NAV_ENTRY_PENDING && 126 if (type == content::NOTIFICATION_NAV_ENTRY_PENDING &&
113 content::Source<NavigationController>(source).ptr() != controller_) { 127 content::Source<NavigationController>(source).ptr() != controller) {
114 NOTREACHED(); 128 NOTREACHED();
115 return; 129 return;
116 } 130 }
117 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED && 131 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED &&
118 &content::Source<content::WebContents>(source).ptr()-> 132 &content::Source<content::WebContents>(source).ptr()->
119 GetController() != controller_) { 133 GetController() != controller) {
120 NOTREACHED(); 134 NOTREACHED();
121 return; 135 return;
122 } 136 }
123 137
124 switch (type) { 138 switch (type) {
125 case content::NOTIFICATION_NAV_ENTRY_PENDING: { 139 case content::NOTIFICATION_NAV_ENTRY_PENDING: {
126 // NOTE: resetting state on a pending navigate isn't ideal. In particular 140 // NOTE: resetting state on a pending navigate isn't ideal. In particular
127 // it is possible that queued up downloads for the page before the 141 // it is possible that queued up downloads for the page before the
128 // pending navigate will be delivered to us after we process this 142 // pending navigate will be delivered to us after we process this
129 // request. If this happens we may let a download through that we 143 // request. If this happens we may let a download through that we
130 // shouldn't have. But this is rather rare, and it is difficult to get 144 // shouldn't have. But this is rather rare, and it is difficult to get
131 // 100% right, so we don't deal with it. 145 // 100% right, so we don't deal with it.
132 NavigationEntry* entry = controller_->GetPendingEntry(); 146 NavigationEntry* entry = controller->GetPendingEntry();
133 if (!entry) 147 if (!entry)
134 return; 148 return;
135 149
136 if (content::PageTransitionIsRedirect(entry->GetTransitionType())) { 150 if (content::PageTransitionIsRedirect(entry->GetTransitionType())) {
137 // Redirects don't count. 151 // Redirects don't count.
138 return; 152 return;
139 } 153 }
140 154
141 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS || 155 if (status_ == DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS ||
142 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) { 156 status_ == DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED) {
(...skipping 15 matching lines...) Expand all
158 172
159 default: 173 default:
160 NOTREACHED(); 174 NOTREACHED();
161 } 175 }
162 176
163 NotifyCallbacks(false); 177 NotifyCallbacks(false);
164 host_->Remove(this); 178 host_->Remove(this);
165 } 179 }
166 180
167 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) { 181 void DownloadRequestLimiter::TabDownloadState::NotifyCallbacks(bool allow) {
168 status_ = allow ? 182 set_download_status(allow ?
169 DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS : 183 DownloadRequestLimiter::ALLOW_ALL_DOWNLOADS :
170 DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED; 184 DownloadRequestLimiter::DOWNLOADS_NOT_ALLOWED);
171 std::vector<DownloadRequestLimiter::Callback> callbacks; 185 std::vector<DownloadRequestLimiter::Callback> callbacks;
172 bool change_status = false; 186 bool change_status = false;
173 187
174 // Selectively send first few notifications only if number of downloads exceed 188 // Selectively send first few notifications only if number of downloads exceed
175 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and 189 // kMaxDownloadsAtOnce. In that case, we also retain the infobar instance and
176 // don't close it. If allow is false, we send all the notifications to cancel 190 // don't close it. If allow is false, we send all the notifications to cancel
177 // all remaining downloads and close the infobar. 191 // all remaining downloads and close the infobar.
178 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) { 192 if (!allow || (callbacks_.size() < kMaxDownloadsAtOnce)) {
179 if (infobar_) { 193 if (infobar_) {
180 // Reset the delegate so we don't get notified again. 194 // Reset the delegate so we don't get notified again.
181 infobar_->set_host(NULL); 195 infobar_->set_host(NULL);
182 infobar_ = NULL; 196 infobar_ = NULL;
183 } 197 }
184 callbacks.swap(callbacks_); 198 callbacks.swap(callbacks_);
185 } else { 199 } else {
186 std::vector<DownloadRequestLimiter::Callback>::iterator start, end; 200 std::vector<DownloadRequestLimiter::Callback>::iterator start, end;
187 start = callbacks_.begin(); 201 start = callbacks_.begin();
188 end = callbacks_.begin() + kMaxDownloadsAtOnce; 202 end = callbacks_.begin() + kMaxDownloadsAtOnce;
189 callbacks.assign(start, end); 203 callbacks.assign(start, end);
190 callbacks_.erase(start, end); 204 callbacks_.erase(start, end);
191 change_status = true; 205 change_status = true;
192 } 206 }
193 207
194 for (size_t i = 0; i < callbacks.size(); ++i) 208 for (size_t i = 0; i < callbacks.size(); ++i)
195 host_->ScheduleNotification(callbacks[i], allow); 209 host_->ScheduleNotification(callbacks[i], allow);
196 210
197 if (change_status) 211 if (change_status)
198 status_ = DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD; 212 set_download_status(DownloadRequestLimiter::PROMPT_BEFORE_DOWNLOAD);
199 } 213 }
200 214
201 // DownloadRequestLimiter ------------------------------------------------------ 215 // DownloadRequestLimiter ------------------------------------------------------
202 216
203 DownloadRequestLimiter::DownloadRequestLimiter() { 217 DownloadRequestLimiter::DownloadRequestLimiter() {
204 } 218 }
205 219
206 DownloadRequestLimiter::~DownloadRequestLimiter() { 220 DownloadRequestLimiter::~DownloadRequestLimiter() {
207 // All the tabs should have closed before us, which sends notification and 221 // All the tabs should have closed before us, which sends notification and
208 // removes from state_map_. As such, there should be no pending callbacks. 222 // removes from state_map_. As such, there should be no pending callbacks.
209 DCHECK(state_map_.empty()); 223 DCHECK(state_map_.empty());
210 } 224 }
211 225
212 DownloadRequestLimiter::DownloadStatus 226 DownloadRequestLimiter::DownloadStatus
213 DownloadRequestLimiter::GetDownloadStatus(WebContents* tab) { 227 DownloadRequestLimiter::GetDownloadStatus(WebContents* web_contents) {
214 TabDownloadState* state = GetDownloadState(&tab->GetController(), NULL, false) ; 228 TabDownloadState* state = GetDownloadState(web_contents, NULL, false);
215 return state ? state->download_status() : ALLOW_ONE_DOWNLOAD; 229 return state ? state->download_status() : ALLOW_ONE_DOWNLOAD;
216 } 230 }
217 231
218 void DownloadRequestLimiter::CanDownloadOnIOThread( 232 void DownloadRequestLimiter::CanDownloadOnIOThread(
219 int render_process_host_id, 233 int render_process_host_id,
220 int render_view_id, 234 int render_view_id,
221 int request_id, 235 int request_id,
222 const std::string& request_method, 236 const std::string& request_method,
223 const Callback& callback) { 237 const Callback& callback) {
224 // This is invoked on the IO thread. Schedule the task to run on the UI 238 // This is invoked on the IO thread. Schedule the task to run on the UI
225 // thread so that we can query UI state. 239 // thread so that we can query UI state.
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 240 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
227 BrowserThread::PostTask( 241 BrowserThread::PostTask(
228 BrowserThread::UI, FROM_HERE, 242 BrowserThread::UI, FROM_HERE,
229 base::Bind(&DownloadRequestLimiter::CanDownload, this, 243 base::Bind(&DownloadRequestLimiter::CanDownload, this,
230 render_process_host_id, render_view_id, request_id, 244 render_process_host_id, render_view_id, request_id,
231 request_method, callback)); 245 request_method, callback));
232 } 246 }
233 247
234 void DownloadRequestLimiter::OnUserGesture(WebContents* tab) {
235 TabDownloadState* state =
236 GetDownloadState(&tab->GetController(), NULL, false);
237 if (!state)
238 return;
239
240 state->OnUserGesture();
241 }
242
243 // static 248 // static
244 void DownloadRequestLimiter::SetTestingDelegate(TestingDelegate* delegate) { 249 void DownloadRequestLimiter::SetTestingDelegate(TestingDelegate* delegate) {
245 delegate_ = delegate; 250 delegate_ = delegate;
246 } 251 }
247 252
248 DownloadRequestLimiter::TabDownloadState* DownloadRequestLimiter:: 253 DownloadRequestLimiter::TabDownloadState*
249 GetDownloadState(NavigationController* controller, 254 DownloadRequestLimiter::GetDownloadState(
250 NavigationController* originating_controller, 255 WebContents* web_contents,
251 bool create) { 256 WebContents* originating_web_contents,
252 DCHECK(controller); 257 bool create) {
253 StateMap::iterator i = state_map_.find(controller); 258 DCHECK(web_contents);
259 StateMap::iterator i = state_map_.find(web_contents);
254 if (i != state_map_.end()) 260 if (i != state_map_.end())
255 return i->second; 261 return i->second;
256 262
257 if (!create) 263 if (!create)
258 return NULL; 264 return NULL;
259 265
260 TabDownloadState* state = 266 TabDownloadState* state =
261 new TabDownloadState(this, controller, originating_controller); 267 new TabDownloadState(this, web_contents, originating_web_contents);
262 state_map_[controller] = state; 268 state_map_[web_contents] = state;
263 return state; 269 return state;
264 } 270 }
265 271
266 void DownloadRequestLimiter::CanDownload(int render_process_host_id, 272 void DownloadRequestLimiter::CanDownload(int render_process_host_id,
267 int render_view_id, 273 int render_view_id,
268 int request_id, 274 int request_id,
269 const std::string& request_method, 275 const std::string& request_method,
270 const Callback& callback) { 276 const Callback& callback) {
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
272 278
273 WebContents* originating_tab = 279 WebContents* originating_contents =
274 tab_util::GetWebContentsByID(render_process_host_id, render_view_id); 280 tab_util::GetWebContentsByID(render_process_host_id, render_view_id);
275 if (!originating_tab) { 281 if (!originating_contents) {
276 // The tab was closed, don't allow the download. 282 // The WebContents was closed, don't allow the download.
277 ScheduleNotification(callback, false); 283 ScheduleNotification(callback, false);
278 return; 284 return;
279 } 285 }
280 286
281 CanDownloadImpl( 287 CanDownloadImpl(
282 TabContentsWrapper::GetCurrentWrapperForContents(originating_tab), 288 originating_contents,
283 request_id, 289 request_id,
284 request_method, 290 request_method,
285 callback); 291 callback);
286 } 292 }
287 293
288 void DownloadRequestLimiter::CanDownloadImpl( 294 void DownloadRequestLimiter::CanDownloadImpl(WebContents* originating_contents,
289 TabContentsWrapper* originating_tab, 295 int request_id,
290 int request_id, 296 const std::string& request_method,
291 const std::string& request_method, 297 const Callback& callback) {
292 const Callback& callback) { 298 DCHECK(originating_contents);
293 DCHECK(originating_tab);
294 299
295 // FYI: Chrome Frame overrides CanDownload in ExternalTabContainer in order 300 // FYI: Chrome Frame overrides CanDownload in ExternalTabContainer in order
296 // to cancel the download operation in chrome and let the host browser 301 // to cancel the download operation in chrome and let the host browser
297 // take care of it. 302 // take care of it.
298 WebContents* tab = originating_tab->web_contents(); 303 if (originating_contents->GetDelegate() &&
299 if (tab->GetDelegate() && !tab->GetDelegate()->CanDownload( 304 !originating_contents->GetDelegate()->CanDownload(
300 tab->GetRenderViewHost(), request_id, request_method)) { 305 originating_contents->GetRenderViewHost(),
306 request_id,
307 request_method)) {
301 ScheduleNotification(callback, false); 308 ScheduleNotification(callback, false);
302 return; 309 return;
303 } 310 }
304 311
305 // If the tab requesting the download is a constrained popup that is not 312 // If the tab requesting the download is a constrained popup that is not
306 // shown, treat the request as if it came from the parent. 313 // shown, treat the request as if it came from the parent.
307 TabContentsWrapper* effective_wrapper = originating_tab; 314 WebContents* effective_contents = originating_contents;
308 if (effective_wrapper->blocked_content_tab_helper()->delegate()) { 315 TabContentsWrapper* originating_wrapper =
309 effective_wrapper = effective_wrapper->blocked_content_tab_helper()-> 316 TabContentsWrapper::GetCurrentWrapperForContents(originating_contents);
310 delegate()->GetConstrainingContentsWrapper(effective_wrapper); 317 if (originating_wrapper &&
318 originating_wrapper->blocked_content_tab_helper()->delegate()) {
319 effective_contents = originating_wrapper->blocked_content_tab_helper()->
320 delegate()->GetConstrainingContentsWrapper(originating_wrapper)->
321 web_contents();
311 } 322 }
312 323
313 TabDownloadState* state = GetDownloadState( 324 TabDownloadState* state = GetDownloadState(
314 &effective_wrapper->web_contents()->GetController(), 325 effective_contents, originating_contents, true);
315 &tab->GetController(), true);
316 switch (state->download_status()) { 326 switch (state->download_status()) {
317 case ALLOW_ALL_DOWNLOADS: 327 case ALLOW_ALL_DOWNLOADS:
318 if (state->download_count() && !(state->download_count() % 328 if (state->download_count() && !(state->download_count() %
319 DownloadRequestLimiter::kMaxDownloadsAtOnce)) 329 DownloadRequestLimiter::kMaxDownloadsAtOnce))
320 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 330 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
321 ScheduleNotification(callback, true); 331 ScheduleNotification(callback, true);
322 state->increment_download_count(); 332 state->increment_download_count();
323 break; 333 break;
324 334
325 case ALLOW_ONE_DOWNLOAD: 335 case ALLOW_ONE_DOWNLOAD:
326 state->set_download_status(PROMPT_BEFORE_DOWNLOAD); 336 state->set_download_status(PROMPT_BEFORE_DOWNLOAD);
327 ScheduleNotification(callback, true); 337 ScheduleNotification(callback, true);
328 break; 338 break;
329 339
330 case DOWNLOADS_NOT_ALLOWED: 340 case DOWNLOADS_NOT_ALLOWED:
331 ScheduleNotification(callback, false); 341 ScheduleNotification(callback, false);
332 break; 342 break;
333 343
334 case PROMPT_BEFORE_DOWNLOAD: 344 case PROMPT_BEFORE_DOWNLOAD:
335 state->PromptUserForDownload(effective_wrapper->web_contents(), callback); 345 state->PromptUserForDownload(effective_contents, callback);
336 state->increment_download_count(); 346 state->increment_download_count();
337 break; 347 break;
338 348
339 default: 349 default:
340 NOTREACHED(); 350 NOTREACHED();
341 } 351 }
342 } 352 }
343 353
344 void DownloadRequestLimiter::ScheduleNotification(const Callback& callback, 354 void DownloadRequestLimiter::ScheduleNotification(const Callback& callback,
345 bool allow) { 355 bool allow) {
346 BrowserThread::PostTask( 356 BrowserThread::PostTask(
347 BrowserThread::IO, FROM_HERE, base::Bind(callback, allow)); 357 BrowserThread::IO, FROM_HERE, base::Bind(callback, allow));
348 } 358 }
349 359
350 void DownloadRequestLimiter::Remove(TabDownloadState* state) { 360 void DownloadRequestLimiter::Remove(TabDownloadState* state) {
351 DCHECK(ContainsKey(state_map_, state->controller())); 361 DCHECK(ContainsKey(state_map_, state->web_contents()));
352 state_map_.erase(state->controller()); 362 state_map_.erase(state->web_contents());
353 delete state; 363 delete state;
354 } 364 }
355 365
356 // static 366 // static
357 DownloadRequestLimiter::TestingDelegate* DownloadRequestLimiter::delegate_ = 367 DownloadRequestLimiter::TestingDelegate* DownloadRequestLimiter::delegate_ =
358 NULL; 368 NULL;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698