Chromium Code Reviews| 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 "content/browser/download/download_manager_impl.h" | 5 #include "content/browser/download/download_manager_impl.h" |
| 6 | 6 |
| 7 #include <iterator> | 7 #include <iterator> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback.h" | 10 #include "base/callback.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 #include "content/browser/download/download_stats.h" | 23 #include "content/browser/download/download_stats.h" |
| 24 #include "content/browser/renderer_host/render_view_host_impl.h" | 24 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 25 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" | 25 #include "content/browser/renderer_host/resource_dispatcher_host_impl.h" |
| 26 #include "content/browser/web_contents/web_contents_impl.h" | 26 #include "content/browser/web_contents/web_contents_impl.h" |
| 27 #include "content/public/browser/browser_context.h" | 27 #include "content/public/browser/browser_context.h" |
| 28 #include "content/public/browser/browser_thread.h" | 28 #include "content/public/browser/browser_thread.h" |
| 29 #include "content/public/browser/content_browser_client.h" | 29 #include "content/public/browser/content_browser_client.h" |
| 30 #include "content/public/browser/download_interrupt_reasons.h" | 30 #include "content/public/browser/download_interrupt_reasons.h" |
| 31 #include "content/public/browser/download_manager_delegate.h" | 31 #include "content/public/browser/download_manager_delegate.h" |
| 32 #include "content/public/browser/download_persistent_store_info.h" | 32 #include "content/public/browser/download_persistent_store_info.h" |
| 33 #include "content/public/browser/download_url_parameters.h" | |
| 33 #include "content/public/browser/notification_service.h" | 34 #include "content/public/browser/notification_service.h" |
| 34 #include "content/public/browser/notification_types.h" | 35 #include "content/public/browser/notification_types.h" |
| 35 #include "content/public/browser/render_process_host.h" | 36 #include "content/public/browser/render_process_host.h" |
| 36 #include "content/public/browser/web_contents_delegate.h" | 37 #include "content/public/browser/web_contents_delegate.h" |
| 38 #include "net/base/load_flags.h" | |
| 37 #include "net/base/upload_data.h" | 39 #include "net/base/upload_data.h" |
| 38 | 40 |
| 39 // TODO(benjhayden): Change this to DCHECK when we have more debugging | 41 // TODO(benjhayden): Change this to DCHECK when we have more debugging |
| 40 // information from the next dev cycle, before the next stable/beta branch is | 42 // information from the next dev cycle, before the next stable/beta branch is |
| 41 // cut, in order to prevent unnecessary crashes on those channels. If we still | 43 // cut, in order to prevent unnecessary crashes on those channels. If we still |
| 42 // don't have root cause before the dev cycle after the next stable/beta | 44 // don't have root cause before the dev cycle after the next stable/beta |
| 43 // releases, uncomment it out to re-enable debugging checks. Whenever this macro | 45 // releases, uncomment it out to re-enable debugging checks. Whenever this macro |
| 44 // is toggled, the corresponding macro in download_database.cc should also | 46 // is toggled, the corresponding macro in download_database.cc should also |
| 45 // be toggled. When 96627 is fixed, this macro and all its usages can be | 47 // be toggled. When 96627 is fixed, this macro and all its usages can be |
| 46 // deleted or permanently changed to DCHECK as appropriate. | 48 // deleted or permanently changed to DCHECK as appropriate. |
| 47 #define CHECK_96627 CHECK | 49 #define CHECK_96627 CHECK |
| 48 | 50 |
| 49 using content::BrowserThread; | 51 using content::BrowserThread; |
| 50 using content::DownloadId; | 52 using content::DownloadId; |
| 51 using content::DownloadItem; | 53 using content::DownloadItem; |
| 52 using content::DownloadPersistentStoreInfo; | 54 using content::DownloadPersistentStoreInfo; |
| 53 using content::ResourceDispatcherHostImpl; | 55 using content::ResourceDispatcherHostImpl; |
| 54 using content::WebContents; | 56 using content::WebContents; |
| 55 | 57 |
| 56 namespace { | 58 namespace { |
| 57 | 59 |
| 58 // Param structs exist because base::Bind can only handle 6 args. | 60 static const char kHeaderNameKey[] = "name"; |
| 59 struct URLParams { | 61 static const char kHeaderBinaryValueKey[] = "binaryValue"; |
| 60 URLParams(const GURL& url, const GURL& referrer, int64 post_id, bool cache) | 62 static const char kHeaderValueKey[] = "value"; |
| 61 : url_(url), referrer_(referrer), post_id_(post_id), prefer_cache_(cache) {} | |
| 62 GURL url_; | |
| 63 GURL referrer_; | |
| 64 int64 post_id_; | |
| 65 bool prefer_cache_; | |
| 66 }; | |
| 67 | 63 |
| 68 struct RenderParams { | 64 void BeginDownload(content::DownloadUrlParameters* params) { |
| 69 RenderParams(int rpi, int rvi) | 65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 70 : render_process_id_(rpi), render_view_id_(rvi) {} | 66 scoped_ptr<net::URLRequest> request(new net::URLRequest( |
| 71 int render_process_id_; | 67 params->url(), params->resource_dispatcher_host())); |
| 72 int render_view_id_; | 68 request->set_referrer(params->referrer().spec()); |
| 73 }; | 69 request->set_load_flags(request->load_flags() | params->load_flags()); |
| 74 | 70 request->set_method(params->method()); |
| 75 void BeginDownload( | 71 if (!params->post_body().empty()) |
| 76 const URLParams& url_params, | 72 request->AppendBytesToUpload(params->post_body().data(), |
| 77 const content::DownloadSaveInfo& save_info, | 73 params->post_body().size()); |
| 78 ResourceDispatcherHostImpl* resource_dispatcher_host, | 74 if (params->post_id() >= 0) { |
| 79 const RenderParams& render_params, | |
| 80 content::ResourceContext* context, | |
| 81 const content::DownloadManager::OnStartedCallback& callback) { | |
| 82 scoped_ptr<net::URLRequest> request( | |
| 83 new net::URLRequest(url_params.url_, resource_dispatcher_host)); | |
| 84 request->set_referrer(url_params.referrer_.spec()); | |
| 85 if (url_params.post_id_ >= 0) { | |
| 86 // The POST in this case does not have an actual body, and only works | 75 // The POST in this case does not have an actual body, and only works |
| 87 // when retrieving data from cache. This is done because we don't want | 76 // when retrieving data from cache. This is done because we don't want |
| 88 // to do a re-POST without user consent, and currently don't have a good | 77 // to do a re-POST without user consent, and currently don't have a good |
| 89 // plan on how to display the UI for that. | 78 // plan on how to display the UI for that. |
| 90 DCHECK(url_params.prefer_cache_); | 79 DCHECK(params->prefer_cache()); |
| 91 request->set_method("POST"); | 80 DCHECK(params->method() == "POST"); |
| 92 scoped_refptr<net::UploadData> upload_data = new net::UploadData(); | 81 scoped_refptr<net::UploadData> upload_data = new net::UploadData(); |
| 93 upload_data->set_identifier(url_params.post_id_); | 82 upload_data->set_identifier(params->post_id()); |
| 94 request->set_upload(upload_data); | 83 request->set_upload(upload_data); |
| 95 } | 84 } |
| 96 resource_dispatcher_host->BeginDownload( | 85 if (params->extra_headers() != NULL) { |
| 86 for (size_t index = 0; | |
| 87 index < params->extra_headers()->GetSize(); | |
| 88 ++index) { | |
| 89 base::DictionaryValue* header = NULL; | |
| 90 std::string name, value; | |
| 91 CHECK(params->extra_headers()->GetDictionary(index, &header)); | |
| 92 CHECK(header->GetString(kHeaderNameKey, &name)); | |
| 93 if (header->HasKey(kHeaderBinaryValueKey)) { | |
| 94 base::ListValue* binary_value = NULL; | |
| 95 CHECK(header->GetList(kHeaderBinaryValueKey, &binary_value)); | |
| 96 for (size_t char_i = 0; char_i < binary_value->GetSize(); ++char_i) { | |
| 97 int char_value = 0; | |
| 98 CHECK(binary_value->GetInteger(char_i, &char_value)); | |
| 99 if ((0 <= char_value) && | |
| 100 (char_value <= 0xff)) { | |
| 101 value.push_back(char_value); | |
| 102 } | |
| 103 } | |
| 104 } else if (header->HasKey(kHeaderValueKey)) { | |
| 105 CHECK(header->GetString(kHeaderValueKey, &value)); | |
| 106 } | |
| 107 request->SetExtraRequestHeaderByName(name, value, false/*overwrite*/); | |
| 108 } | |
| 109 } | |
|
Randy Smith (Not in Mondays)
2012/04/30 19:44:48
I'm not sure I completely follow this format, but
benjhayden
2012/05/02 15:11:54
Done.
| |
| 110 params->resource_dispatcher_host()->BeginDownload( | |
| 97 request.Pass(), | 111 request.Pass(), |
| 98 context, | 112 params->resource_context(), |
| 99 render_params.render_process_id_, | 113 params->render_process_host_id(), |
| 100 render_params.render_view_id_, | 114 params->render_view_host_routing_id(), |
| 101 url_params.prefer_cache_, | 115 params->prefer_cache(), |
| 102 save_info, | 116 params->save_info(), |
| 103 callback); | 117 params->callback()); |
| 104 } | 118 } |
| 105 | 119 |
| 106 class MapValueIteratorAdapter { | 120 class MapValueIteratorAdapter { |
| 107 public: | 121 public: |
| 108 explicit MapValueIteratorAdapter( | 122 explicit MapValueIteratorAdapter( |
| 109 base::hash_map<int64, DownloadItem*>::const_iterator iter) | 123 base::hash_map<int64, DownloadItem*>::const_iterator iter) |
| 110 : iter_(iter) { | 124 : iter_(iter) { |
| 111 } | 125 } |
| 112 ~MapValueIteratorAdapter() {} | 126 ~MapValueIteratorAdapter() {} |
| 113 | 127 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 141 BrowserThread::PostTask( | 155 BrowserThread::PostTask( |
| 142 BrowserThread::FILE, FROM_HERE, | 156 BrowserThread::FILE, FROM_HERE, |
| 143 base::Bind(&EnsureNoPendingDownloadsOnFile, | 157 base::Bind(&EnsureNoPendingDownloadsOnFile, |
| 144 download_file_manager, result)); | 158 download_file_manager, result)); |
| 145 } | 159 } |
| 146 | 160 |
| 147 } // namespace | 161 } // namespace |
| 148 | 162 |
| 149 namespace content { | 163 namespace content { |
| 150 | 164 |
| 165 DownloadUrlParameters::DownloadUrlParameters( | |
| 166 const GURL& url, | |
| 167 int render_process_host_id, | |
| 168 int render_view_host_routing_id, | |
| 169 content::ResourceContext* resource_context, | |
| 170 const content::DownloadSaveInfo& save_info) | |
| 171 : extra_headers_(NULL), | |
| 172 load_flags_(0), | |
| 173 method_("GET"), | |
| 174 post_id_(-1), | |
| 175 prefer_cache_(false), | |
| 176 render_process_host_id_(render_process_host_id), | |
| 177 render_view_host_routing_id_(render_view_host_routing_id), | |
| 178 resource_context_(resource_context), | |
| 179 resource_dispatcher_host_(ResourceDispatcherHostImpl::Get()), | |
| 180 save_info_(save_info), | |
| 181 url_(url) { | |
| 182 DCHECK(resource_dispatcher_host_); | |
| 183 } | |
| 184 | |
| 185 DownloadUrlParameters::~DownloadUrlParameters() { | |
| 186 } | |
| 187 | |
| 188 // static | |
| 189 DownloadUrlParameters* DownloadUrlParameters::FromWebContents( | |
| 190 WebContents* web_contents, | |
| 191 const GURL& url, | |
| 192 const content::DownloadSaveInfo& save_info) { | |
| 193 return new DownloadUrlParameters( | |
| 194 url, | |
| 195 web_contents->GetRenderProcessHost()->GetID(), | |
| 196 web_contents->GetRenderViewHost()->GetRoutingID(), | |
| 197 web_contents->GetBrowserContext()->GetResourceContext(), | |
| 198 save_info); | |
| 199 } | |
| 200 | |
| 201 | |
| 151 // static | 202 // static |
| 152 DownloadManager* DownloadManager::Create( | 203 DownloadManager* DownloadManager::Create( |
| 153 content::DownloadManagerDelegate* delegate, | 204 content::DownloadManagerDelegate* delegate, |
| 154 net::NetLog* net_log) { | 205 net::NetLog* net_log) { |
| 155 return new DownloadManagerImpl(delegate, net_log); | 206 return new DownloadManagerImpl(delegate, net_log); |
| 156 } | 207 } |
| 157 | 208 |
| 158 bool DownloadManager::EnsureNoPendingDownloadsForTesting() { | 209 bool DownloadManager::EnsureNoPendingDownloadsForTesting() { |
| 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 160 bool result = true; | 211 bool result = true; |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 int DownloadManagerImpl::RemoveDownloads(base::Time remove_begin) { | 894 int DownloadManagerImpl::RemoveDownloads(base::Time remove_begin) { |
| 844 return RemoveDownloadsBetween(remove_begin, base::Time()); | 895 return RemoveDownloadsBetween(remove_begin, base::Time()); |
| 845 } | 896 } |
| 846 | 897 |
| 847 int DownloadManagerImpl::RemoveAllDownloads() { | 898 int DownloadManagerImpl::RemoveAllDownloads() { |
| 848 download_stats::RecordClearAllSize(history_downloads_.size()); | 899 download_stats::RecordClearAllSize(history_downloads_.size()); |
| 849 // The null times make the date range unbounded. | 900 // The null times make the date range unbounded. |
| 850 return RemoveDownloadsBetween(base::Time(), base::Time()); | 901 return RemoveDownloadsBetween(base::Time(), base::Time()); |
| 851 } | 902 } |
| 852 | 903 |
| 853 // Initiate a download of a specific URL. We send the request to the | |
| 854 // ResourceDispatcherHost, and let it send us responses like a regular | |
| 855 // download. | |
| 856 void DownloadManagerImpl::DownloadUrl( | 904 void DownloadManagerImpl::DownloadUrl( |
| 857 const GURL& url, | 905 content::DownloadUrlParameters* parameters) { |
| 858 const GURL& referrer, | 906 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( |
| 859 const std::string& referrer_charset, | 907 &BeginDownload, base::Owned(parameters))); |
| 860 bool prefer_cache, | |
| 861 int64 post_id, | |
| 862 const content::DownloadSaveInfo& save_info, | |
| 863 WebContents* web_contents, | |
| 864 const OnStartedCallback& callback) { | |
| 865 ResourceDispatcherHostImpl* resource_dispatcher_host = | |
| 866 ResourceDispatcherHostImpl::Get(); | |
| 867 DCHECK(resource_dispatcher_host); | |
| 868 | |
| 869 // We send a pointer to content::ResourceContext, instead of the usual | |
| 870 // reference, so that a copy of the object isn't made. | |
| 871 // base::Bind can't handle 7 args, so we use URLParams and RenderParams. | |
| 872 BrowserThread::PostTask( | |
| 873 BrowserThread::IO, FROM_HERE, | |
| 874 base::Bind( | |
| 875 &BeginDownload, | |
| 876 URLParams(url, referrer, post_id, prefer_cache), | |
| 877 save_info, | |
| 878 resource_dispatcher_host, | |
| 879 RenderParams(web_contents->GetRenderProcessHost()->GetID(), | |
| 880 web_contents->GetRenderViewHost()->GetRoutingID()), | |
| 881 web_contents->GetBrowserContext()->GetResourceContext(), | |
| 882 callback)); | |
| 883 } | 908 } |
| 884 | 909 |
| 885 void DownloadManagerImpl::AddObserver(Observer* observer) { | 910 void DownloadManagerImpl::AddObserver(Observer* observer) { |
| 886 observers_.AddObserver(observer); | 911 observers_.AddObserver(observer); |
| 887 // TODO: It is the responsibility of the observers to query the | 912 // TODO: It is the responsibility of the observers to query the |
| 888 // DownloadManager. Remove the following call from here and update all | 913 // DownloadManager. Remove the following call from here and update all |
| 889 // observers. | 914 // observers. |
| 890 observer->ModelChanged(this); | 915 observer->ModelChanged(this); |
| 891 } | 916 } |
| 892 | 917 |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1208 if (it->second->IsComplete() && !it->second->GetOpened()) | 1233 if (it->second->IsComplete() && !it->second->GetOpened()) |
| 1209 ++num_unopened; | 1234 ++num_unopened; |
| 1210 } | 1235 } |
| 1211 download_stats::RecordOpensOutstanding(num_unopened); | 1236 download_stats::RecordOpensOutstanding(num_unopened); |
| 1212 } | 1237 } |
| 1213 | 1238 |
| 1214 void DownloadManagerImpl::SetFileManagerForTesting( | 1239 void DownloadManagerImpl::SetFileManagerForTesting( |
| 1215 DownloadFileManager* file_manager) { | 1240 DownloadFileManager* file_manager) { |
| 1216 file_manager_ = file_manager; | 1241 file_manager_ = file_manager; |
| 1217 } | 1242 } |
| OLD | NEW |