| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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; |
| OLD | NEW |