#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager_delegate.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/common/resource_response.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request_context.h"
namespace content {
+
+struct DownloadResourceHandler::DownloadTabInfo {
+ GURL tab_url;
+ GURL tab_referrer_url;
+};
+
namespace {
void CallStartedCBOnUIThread(
// DownloadResourceHandler members from the UI thread.
static void StartOnUIThread(
scoped_ptr<DownloadCreateInfo> info,
+ DownloadResourceHandler::DownloadTabInfo* tab_info,
scoped_ptr<ByteStreamReader> stream,
const DownloadUrlParameters::OnStartedCallback& started_cb) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// download.
if (!started_cb.is_null())
started_cb.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
+
+ // |stream| gets deleted on non-FILE thread, but it's ok since
+ // we're not using stream_writer_ yet.
+
return;
}
+ info->tab_url = tab_info->tab_url;
+ info->tab_referrer_url = tab_info->tab_referrer_url;
+
download_manager->StartDownload(info.Pass(), stream.Pass(), started_cb);
}
+void InitializeDownloadTabInfoOnUIThread(
+ const DownloadRequestHandle& request_handle,
+ DownloadResourceHandler::DownloadTabInfo* tab_info) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ WebContents* web_contents = request_handle.GetWebContents();
+ if (web_contents) {
+ NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
+ if (entry) {
+ tab_info->tab_url = entry->GetURL();
+ tab_info->tab_referrer_url = entry->GetReferrer().url;
+ }
+ }
+}
+
} // namespace
const int DownloadResourceHandler::kDownloadByteStreamSize = 100 * 1024;
was_deferred_(false),
on_response_started_called_(false) {
RecordDownloadCount(UNTHROTTLED_COUNT);
+
+ // Do UI thread initialization asap after DownloadResourceHandler creation
+ // since the tab could be navigated before StartOnUIThread gets called.
+ const ResourceRequestInfoImpl* request_info = GetRequestInfo();
+ tab_info_ = new DownloadTabInfo();
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&InitializeDownloadTabInfoOnUIThread,
+ DownloadRequestHandle(AsWeakPtr(),
+ request_info->GetChildID(),
+ request_info->GetRouteID(),
+ request_info->GetRequestID()),
+ tab_info_));
}
bool DownloadResourceHandler::OnUploadProgress(int request_id,
info->original_mime_type.clear();
}
+ // Blink verifies that the requester of this download is allowed to set a
+ // suggested name for the security origin of the downlaod URL. However, this
+ // assumption doesn't hold if there were cross origin redirects. Therefore,
+ // clear the suggested_name for such requests.
+ if (info->url_chain.size() > 1 &&
+ info->url_chain.front().GetOrigin() != info->url_chain.back().GetOrigin())
+ info->save_info->suggested_name.clear();
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&StartOnUIThread,
base::Passed(&info),
+ base::Owned(tab_info_),
base::Passed(&stream_reader),
// Pass to StartOnUIThread so that variable
// access is always on IO thread but function
// is called on UI thread.
started_cb_));
+ // Now owned by the task that was just posted.
+ tab_info_ = NULL;
// Guaranteed to be called in StartOnUIThread
started_cb_.Reset();
if (stream_writer_)
stream_writer_->RegisterCallback(base::Closure());
+ // tab_info_ must be destroyed on UI thread, since
+ // InitializeDownloadTabInfoOnUIThread might still be using it.
+ if (tab_info_)
+ BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, tab_info_);
+
UMA_HISTOGRAM_TIMES("SB2.DownloadDuration",
base::TimeTicks::Now() - download_start_time_);
}