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

Side by Side Diff: content/browser/download/save_file_manager.cc

Issue 1484093002: Allowing multiple SaveItems to have same URLs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@nested-frames-more-involved-fix
Patch Set: Rebasing... Created 5 years 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
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 "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #include "content/browser/download/save_file_manager.h" 7 #include "content/browser/download/save_file_manager.h"
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/stl_util.h" 12 #include "base/stl_util.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/threading/thread.h" 14 #include "base/threading/thread.h"
15 #include "content/browser/download/save_file.h" 15 #include "content/browser/download/save_file.h"
16 #include "content/browser/download/save_package.h" 16 #include "content/browser/download/save_package.h"
17 #include "content/browser/loader/resource_dispatcher_host_impl.h" 17 #include "content/browser/loader/resource_dispatcher_host_impl.h"
18 #include "content/browser/renderer_host/render_view_host_impl.h" 18 #include "content/browser/renderer_host/render_view_host_impl.h"
19 #include "content/browser/web_contents/web_contents_impl.h" 19 #include "content/browser/web_contents/web_contents_impl.h"
20 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/render_frame_host.h" 21 #include "content/public/browser/render_frame_host.h"
22 #include "net/base/filename_util.h" 22 #include "net/base/filename_util.h"
23 #include "net/base/io_buffer.h" 23 #include "net/base/io_buffer.h"
24 #include "url/gurl.h" 24 #include "url/gurl.h"
25 25
26 namespace content { 26 namespace content {
27 27
28 SaveFileManager::SaveFileManager() 28 SaveFileManager::SaveFileManager() {}
29 : next_id_(0) {
30 }
31 29
32 SaveFileManager::~SaveFileManager() { 30 SaveFileManager::~SaveFileManager() {
33 // Check for clean shutdown. 31 // Check for clean shutdown.
34 DCHECK(save_file_map_.empty()); 32 DCHECK(save_file_map_.empty());
35 } 33 }
36 34
37 // Called during the browser shutdown process to clean up any state (open files, 35 // Called during the browser shutdown process to clean up any state (open files,
38 // timers) that live on the saving thread (file thread). 36 // timers) that live on the saving thread (file thread).
39 void SaveFileManager::Shutdown() { 37 void SaveFileManager::Shutdown() {
40 BrowserThread::PostTask( 38 BrowserThread::PostTask(
41 BrowserThread::FILE, FROM_HERE, 39 BrowserThread::FILE, FROM_HERE,
42 base::Bind(&SaveFileManager::OnShutdown, this)); 40 base::Bind(&SaveFileManager::OnShutdown, this));
43 } 41 }
44 42
45 // Stop file thread operations. 43 // Stop file thread operations.
46 void SaveFileManager::OnShutdown() { 44 void SaveFileManager::OnShutdown() {
47 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 45 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
48 STLDeleteValues(&save_file_map_); 46 STLDeleteValues(&save_file_map_);
49 } 47 }
50 48
51 SaveFile* SaveFileManager::LookupSaveFile(int save_id) { 49 SaveFile* SaveFileManager::LookupSaveFile(int save_item_id) {
52 SaveFileMap::iterator it = save_file_map_.find(save_id); 50 SaveFileMap::iterator it = save_file_map_.find(save_item_id);
53 return it == save_file_map_.end() ? NULL : it->second; 51 return it == save_file_map_.end() ? NULL : it->second;
54 } 52 }
55 53
56 // Called on the IO thread when 54 // Look up a SavePackage according to a save id.
57 // a) The ResourceDispatcherHostImpl has decided that a request is savable. 55 SavePackage* SaveFileManager::LookupPackage(int save_item_id) {
58 // b) The resource does not come from the network, but we still need a
59 // save ID for for managing the status of the saving operation. So we
60 // file a request from the file thread to the IO thread to generate a
61 // unique save ID.
62 int SaveFileManager::GetNextId() {
63 DCHECK_CURRENTLY_ON(BrowserThread::IO);
64 return next_id_++;
65 }
66
67 void SaveFileManager::RegisterStartingRequest(const GURL& save_url,
68 SavePackage* save_package) {
69 // Make sure it runs in the UI thread.
70 DCHECK_CURRENTLY_ON(BrowserThread::UI); 56 DCHECK_CURRENTLY_ON(BrowserThread::UI);
71 int save_package_id = save_package->id(); 57 SavePackageMap::iterator it = packages_.find(save_item_id);
72
73 // Register this starting request.
74 StartingRequestsMap& starting_requests =
75 contents_starting_requests_[save_package_id];
76 bool never_present = starting_requests.insert(
77 StartingRequestsMap::value_type(save_url.spec(), save_package)).second;
78 DCHECK(never_present);
79 }
80
81 SavePackage* SaveFileManager::UnregisterStartingRequest(const GURL& save_url,
82 int save_package_id) {
83 // Make sure it runs in UI thread.
84 DCHECK_CURRENTLY_ON(BrowserThread::UI);
85
86 ContentsToStartingRequestsMap::iterator it =
87 contents_starting_requests_.find(save_package_id);
88 if (it != contents_starting_requests_.end()) {
89 StartingRequestsMap& requests = it->second;
90 StartingRequestsMap::iterator sit = requests.find(save_url.spec());
91 if (sit == requests.end())
92 return NULL;
93
94 // Found, erase it from starting list and return SavePackage.
95 SavePackage* save_package = sit->second;
96 requests.erase(sit);
97 // If there is no element in requests, remove it
98 if (requests.empty())
99 contents_starting_requests_.erase(it);
100 return save_package;
101 }
102
103 return NULL;
104 }
105
106 // Look up a SavePackage according to a save id.
107 SavePackage* SaveFileManager::LookupPackage(int save_id) {
108 DCHECK_CURRENTLY_ON(BrowserThread::UI);
109 SavePackageMap::iterator it = packages_.find(save_id);
110 if (it != packages_.end()) 58 if (it != packages_.end())
111 return it->second; 59 return it->second;
112 return NULL; 60 return NULL;
113 } 61 }
114 62
115 // Call from SavePackage for starting a saving job 63 // Call from SavePackage for starting a saving job
116 void SaveFileManager::SaveURL(const GURL& url, 64 void SaveFileManager::SaveURL(int save_item_id,
65 const GURL& url,
117 const Referrer& referrer, 66 const Referrer& referrer,
118 int render_process_host_id, 67 int render_process_host_id,
119 int render_view_routing_id, 68 int render_view_routing_id,
120 int render_frame_routing_id, 69 int render_frame_routing_id,
121 SaveFileCreateInfo::SaveFileSource save_source, 70 SaveFileCreateInfo::SaveFileSource save_source,
122 const base::FilePath& file_full_path, 71 const base::FilePath& file_full_path,
123 ResourceContext* context, 72 ResourceContext* context,
124 SavePackage* save_package) { 73 SavePackage* save_package) {
125 DCHECK_CURRENTLY_ON(BrowserThread::UI); 74 DCHECK_CURRENTLY_ON(BrowserThread::UI);
126 75
127 // Register a saving job. 76 // Register a saving job.
128 RegisterStartingRequest(url, save_package);
129 if (save_source == SaveFileCreateInfo::SAVE_FILE_FROM_NET) { 77 if (save_source == SaveFileCreateInfo::SAVE_FILE_FROM_NET) {
130 DCHECK(url.is_valid()); 78 DCHECK(url.is_valid());
131 79
132 BrowserThread::PostTask( 80 BrowserThread::PostTask(
133 BrowserThread::IO, FROM_HERE, 81 BrowserThread::IO, FROM_HERE,
134 base::Bind(&SaveFileManager::OnSaveURL, this, url, referrer, 82 base::Bind(&SaveFileManager::OnSaveURL, this, url, referrer,
135 save_package->id(), render_process_host_id, 83 save_item_id, save_package->id(), render_process_host_id,
136 render_view_routing_id, render_frame_routing_id, context)); 84 render_view_routing_id, render_frame_routing_id, context));
137 } else { 85 } else {
138 // We manually start the save job. 86 // We manually start the save job.
139 SaveFileCreateInfo* info = new SaveFileCreateInfo(file_full_path, 87 SaveFileCreateInfo* info = new SaveFileCreateInfo(
140 url, 88 file_full_path, url, save_item_id, save_package->id(),
141 save_source, 89 render_process_host_id, render_frame_routing_id, save_source);
142 -1);
143 info->render_process_id = render_process_host_id;
144 info->render_frame_routing_id = render_frame_routing_id;
145 info->save_package_id = save_package->id();
146 90
147 // Since the data will come from render process, so we need to start 91 // Since the data will come from render process, so we need to start
148 // this kind of save job by ourself. 92 // this kind of save job by ourself.
149 BrowserThread::PostTask( 93 BrowserThread::PostTask(
150 BrowserThread::IO, FROM_HERE, 94 BrowserThread::FILE, FROM_HERE,
151 base::Bind(&SaveFileManager::OnRequireSaveJobFromOtherSource, 95 base::Bind(&SaveFileManager::StartSave, this, info));
152 this, info));
153 } 96 }
154 } 97 }
155 98
156 // Utility function for look up table maintenance, called on the UI thread. 99 // Utility function for look up table maintenance, called on the UI thread.
157 // A manager may have multiple save page job (SavePackage) in progress, 100 // A manager may have multiple save page job (SavePackage) in progress,
158 // so we just look up the save id and remove it from the tracking table. 101 // so we just look up the save id and remove it from the tracking table.
159 // If the save id is -1, it means we just send a request to save, but the 102 void SaveFileManager::RemoveSaveFile(int save_item_id,
160 // saving action has still not happened, need to call UnregisterStartingRequest
161 // to remove it from the tracking map.
162 void SaveFileManager::RemoveSaveFile(int save_id,
163 const GURL& save_url,
164 SavePackage* save_package) { 103 SavePackage* save_package) {
165 DCHECK(save_package); 104 DCHECK(save_package);
166 DCHECK_CURRENTLY_ON(BrowserThread::UI); 105 DCHECK_CURRENTLY_ON(BrowserThread::UI);
167 // A save page job (SavePackage) can only have one manager, 106 // A save page job (SavePackage) can only have one manager,
168 // so remove it if it exists. 107 // so remove it if it exists.
169 if (save_id == -1) { 108 SavePackageMap::iterator it = packages_.find(save_item_id);
170 SavePackage* old_package = 109 if (it != packages_.end())
171 UnregisterStartingRequest(save_url, save_package->id()); 110 packages_.erase(it);
172 DCHECK_EQ(old_package, save_package);
173 } else {
174 SavePackageMap::iterator it = packages_.find(save_id);
175 if (it != packages_.end())
176 packages_.erase(it);
177 }
178 } 111 }
179 112
180 // Static 113 // Static
181 SavePackage* SaveFileManager::GetSavePackageFromRenderIds( 114 SavePackage* SaveFileManager::GetSavePackageFromRenderIds(
182 int render_process_id, 115 int render_process_id,
183 int render_frame_routing_id) { 116 int render_frame_routing_id) {
184 RenderFrameHost* render_frame_host = 117 RenderFrameHost* render_frame_host =
185 RenderFrameHost::FromID(render_process_id, render_frame_routing_id); 118 RenderFrameHost::FromID(render_process_id, render_frame_routing_id);
186 if (!render_frame_host) 119 if (!render_frame_host)
187 return nullptr; 120 return nullptr;
188 121
189 WebContentsImpl* web_contents = 122 WebContentsImpl* web_contents =
190 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost( 123 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(
191 render_frame_host)); 124 render_frame_host));
192 if (!web_contents) 125 if (!web_contents)
193 return nullptr; 126 return nullptr;
194 127
195 return web_contents->save_package(); 128 return web_contents->save_package();
196 } 129 }
197 130
198 void SaveFileManager::DeleteDirectoryOrFile(const base::FilePath& full_path, 131 void SaveFileManager::DeleteDirectoryOrFile(const base::FilePath& full_path,
199 bool is_dir) { 132 bool is_dir) {
200 DCHECK_CURRENTLY_ON(BrowserThread::UI); 133 DCHECK_CURRENTLY_ON(BrowserThread::UI);
201 BrowserThread::PostTask( 134 BrowserThread::PostTask(
202 BrowserThread::FILE, FROM_HERE, 135 BrowserThread::FILE, FROM_HERE,
203 base::Bind(&SaveFileManager::OnDeleteDirectoryOrFile, 136 base::Bind(&SaveFileManager::OnDeleteDirectoryOrFile,
204 this, full_path, is_dir)); 137 this, full_path, is_dir));
205 } 138 }
206 139
207 void SaveFileManager::SendCancelRequest(int save_id) { 140 void SaveFileManager::SendCancelRequest(int save_item_id) {
208 // Cancel the request which has specific save id. 141 // Cancel the request which has specific save id.
209 DCHECK_GT(save_id, -1); 142 DCHECK_GT(save_item_id, -1);
210 BrowserThread::PostTask( 143 BrowserThread::PostTask(
211 BrowserThread::FILE, FROM_HERE, 144 BrowserThread::FILE, FROM_HERE,
212 base::Bind(&SaveFileManager::CancelSave, this, save_id)); 145 base::Bind(&SaveFileManager::CancelSave, this, save_item_id));
213 } 146 }
214 147
215 // Notifications sent from the IO thread and run on the file thread: 148 // Notifications sent from the IO thread and run on the file thread:
216 149
217 // The IO thread created |info|, but the file thread (this method) uses it 150 // The IO thread created |info|, but the file thread (this method) uses it
218 // to create a SaveFile which will hold and finally destroy |info|. It will 151 // to create a SaveFile which will hold and finally destroy |info|. It will
219 // then passes |info| to the UI thread for reporting saving status. 152 // then passes |info| to the UI thread for reporting saving status.
220 void SaveFileManager::StartSave(SaveFileCreateInfo* info) { 153 void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
221 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 154 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
222 DCHECK(info); 155 DCHECK(info);
223 // No need to calculate hash. 156 // No need to calculate hash.
224 SaveFile* save_file = new SaveFile(info, false); 157 SaveFile* save_file = new SaveFile(info, false);
225 158
226 // TODO(phajdan.jr): We should check the return value and handle errors here. 159 // TODO(phajdan.jr): We should check the return value and handle errors here.
227 save_file->Initialize(); 160 save_file->Initialize();
228 161
229 DCHECK(!LookupSaveFile(info->save_id)); 162 DCHECK(!LookupSaveFile(info->save_item_id));
230 save_file_map_[info->save_id] = save_file; 163 save_file_map_[info->save_item_id] = save_file;
231 info->path = save_file->FullPath(); 164 info->path = save_file->FullPath();
232 165
233 BrowserThread::PostTask( 166 BrowserThread::PostTask(
234 BrowserThread::UI, FROM_HERE, 167 BrowserThread::UI, FROM_HERE,
235 base::Bind(&SaveFileManager::OnStartSave, this, info)); 168 base::Bind(&SaveFileManager::OnStartSave, this, info));
236 } 169 }
237 170
238 // We do forward an update to the UI thread here, since we do not use timer to 171 // We do forward an update to the UI thread here, since we do not use timer to
239 // update the UI. If the user has canceled the saving action (in the UI 172 // update the UI. If the user has canceled the saving action (in the UI
240 // thread). We may receive a few more updates before the IO thread gets the 173 // thread). We may receive a few more updates before the IO thread gets the
241 // cancel message. We just delete the data since the SaveFile has been deleted. 174 // cancel message. We just delete the data since the SaveFile has been deleted.
242 void SaveFileManager::UpdateSaveProgress(int save_id, 175 void SaveFileManager::UpdateSaveProgress(int save_item_id,
243 net::IOBuffer* data, 176 net::IOBuffer* data,
244 int data_len) { 177 int data_len) {
245 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 178 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
246 SaveFile* save_file = LookupSaveFile(save_id); 179 SaveFile* save_file = LookupSaveFile(save_item_id);
247 if (save_file) { 180 if (save_file) {
248 DCHECK(save_file->InProgress()); 181 DCHECK(save_file->InProgress());
249 182
250 DownloadInterruptReason reason = 183 DownloadInterruptReason reason =
251 save_file->AppendDataToFile(data->data(), data_len); 184 save_file->AppendDataToFile(data->data(), data_len);
252 BrowserThread::PostTask( 185 BrowserThread::PostTask(
253 BrowserThread::UI, FROM_HERE, 186 BrowserThread::UI, FROM_HERE,
254 base::Bind(&SaveFileManager::OnUpdateSaveProgress, 187 base::Bind(&SaveFileManager::OnUpdateSaveProgress, this,
255 this, 188 save_file->save_item_id(), save_file->BytesSoFar(),
256 save_file->save_id(),
257 save_file->BytesSoFar(),
258 reason == DOWNLOAD_INTERRUPT_REASON_NONE)); 189 reason == DOWNLOAD_INTERRUPT_REASON_NONE));
259 } 190 }
260 } 191 }
261 192
262 // The IO thread will call this when saving is completed or it got error when 193 // The IO thread will call this when saving is completed or it got error when
263 // fetching data. In the former case, we forward the message to OnSaveFinished 194 // fetching data. We forward the message to OnSaveFinished in UI thread.
264 // in UI thread. In the latter case, the save ID will be -1, which means the 195 void SaveFileManager::SaveFinished(int save_item_id,
265 // saving action did not even start, so we need to call OnErrorFinished in UI
266 // thread, which will use the save URL to find corresponding request record and
267 // delete it.
268 void SaveFileManager::SaveFinished(int save_id,
269 const GURL& save_url,
270 int save_package_id, 196 int save_package_id,
271 bool is_success) { 197 bool is_success) {
272 DVLOG(20) << " " << __FUNCTION__ << "()" 198 DVLOG(20) << " " << __FUNCTION__ << "()"
273 << " save_id = " << save_id << " save_url = \"" << save_url.spec() 199 << " save_item_id = " << save_item_id
274 << "\""
275 << " save_package_id = " << save_package_id 200 << " save_package_id = " << save_package_id
276 << " is_success = " << is_success; 201 << " is_success = " << is_success;
277 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 202 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
278 SaveFileMap::iterator it = save_file_map_.find(save_id); 203 SaveFileMap::iterator it = save_file_map_.find(save_item_id);
279 if (it != save_file_map_.end()) { 204 if (it != save_file_map_.end()) {
280 SaveFile* save_file = it->second; 205 SaveFile* save_file = it->second;
281 // This routine may be called twice from the same SavePackage - once for the 206 DCHECK(save_file->InProgress());
282 // file itself, and once when all frames have been serialized.
283 // So we can't assert that the file is InProgress() here.
284 // TODO(rdsmith): Fix this logic and put the DCHECK below back in.
285 // DCHECK(save_file->InProgress());
286 207
287 DVLOG(20) << " " << __FUNCTION__ << "()" 208 DVLOG(20) << " " << __FUNCTION__ << "()"
288 << " save_file = " << save_file->DebugString(); 209 << " save_file = " << save_file->DebugString();
289 BrowserThread::PostTask( 210 BrowserThread::PostTask(
290 BrowserThread::UI, FROM_HERE, 211 BrowserThread::UI, FROM_HERE,
291 base::Bind(&SaveFileManager::OnSaveFinished, this, save_id, 212 base::Bind(&SaveFileManager::OnSaveFinished, this, save_item_id,
292 save_file->BytesSoFar(), is_success)); 213 save_file->BytesSoFar(), is_success));
293 214
294 save_file->Finish(); 215 save_file->Finish();
295 save_file->Detach(); 216 save_file->Detach();
296 } else if (save_id == -1) {
297 // Before saving started, we got error. We still call finish process.
298 DCHECK(!save_url.is_empty());
299 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
300 base::Bind(&SaveFileManager::OnErrorFinished, this,
301 save_url, save_package_id));
302 } 217 }
303 } 218 }
304 219
305 // Notifications sent from the file thread and run on the UI thread. 220 // Notifications sent from the file thread and run on the UI thread.
306 221
307 void SaveFileManager::OnStartSave(const SaveFileCreateInfo* info) { 222 void SaveFileManager::OnStartSave(const SaveFileCreateInfo* info) {
308 DCHECK_CURRENTLY_ON(BrowserThread::UI); 223 DCHECK_CURRENTLY_ON(BrowserThread::UI);
309 SavePackage* save_package = GetSavePackageFromRenderIds( 224 SavePackage* save_package = GetSavePackageFromRenderIds(
310 info->render_process_id, info->render_frame_routing_id); 225 info->render_process_id, info->render_frame_routing_id);
311 if (!save_package) { 226 if (!save_package) {
312 // Cancel this request. 227 // Cancel this request.
313 SendCancelRequest(info->save_id); 228 SendCancelRequest(info->save_item_id);
314 return; 229 return;
315 } 230 }
316 231
317 // Insert started saving job to tracking list. 232 // Insert started saving job to tracking list.
318 SavePackageMap::iterator sit = packages_.find(info->save_id); 233 SavePackageMap::iterator sit = packages_.find(info->save_item_id);
319 if (sit == packages_.end()) { 234 DCHECK(sit == packages_.end());
320 // Find the registered request. If we can not find, it means we have 235 packages_[info->save_item_id] = save_package;
321 // canceled the job before.
322 SavePackage* old_save_package =
323 UnregisterStartingRequest(info->url, info->save_package_id);
324 if (!old_save_package) {
325 // Cancel this request.
326 SendCancelRequest(info->save_id);
327 return;
328 }
329 DCHECK_EQ(old_save_package, save_package);
330 packages_[info->save_id] = save_package;
331 } else {
332 NOTREACHED();
333 }
334 236
335 // Forward this message to SavePackage. 237 // Forward this message to SavePackage.
336 save_package->StartSave(info); 238 save_package->StartSave(info);
337 } 239 }
338 240
339 void SaveFileManager::OnUpdateSaveProgress(int save_id, int64 bytes_so_far, 241 void SaveFileManager::OnUpdateSaveProgress(int save_item_id,
242 int64 bytes_so_far,
340 bool write_success) { 243 bool write_success) {
341 DCHECK_CURRENTLY_ON(BrowserThread::UI); 244 DCHECK_CURRENTLY_ON(BrowserThread::UI);
342 SavePackage* package = LookupPackage(save_id); 245 SavePackage* package = LookupPackage(save_item_id);
343 if (package) 246 if (package)
344 package->UpdateSaveProgress(save_id, bytes_so_far, write_success); 247 package->UpdateSaveProgress(save_item_id, bytes_so_far, write_success);
345 else 248 else
346 SendCancelRequest(save_id); 249 SendCancelRequest(save_item_id);
347 } 250 }
348 251
349 void SaveFileManager::OnSaveFinished(int save_id, 252 void SaveFileManager::OnSaveFinished(int save_item_id,
350 int64 bytes_so_far, 253 int64 bytes_so_far,
351 bool is_success) { 254 bool is_success) {
352 DCHECK_CURRENTLY_ON(BrowserThread::UI); 255 DCHECK_CURRENTLY_ON(BrowserThread::UI);
353 SavePackage* package = LookupPackage(save_id); 256 SavePackage* package = LookupPackage(save_item_id);
354 if (package) 257 if (package)
355 package->SaveFinished(save_id, bytes_so_far, is_success); 258 package->SaveFinished(save_item_id, bytes_so_far, is_success);
356 }
357
358 void SaveFileManager::OnErrorFinished(const GURL& save_url,
359 int save_package_id) {
360 DCHECK_CURRENTLY_ON(BrowserThread::UI);
361 SavePackage* save_package =
362 UnregisterStartingRequest(save_url, save_package_id);
363 if (save_package)
364 save_package->SaveFailed(save_url);
365 } 259 }
366 260
367 // Notifications sent from the UI thread and run on the IO thread. 261 // Notifications sent from the UI thread and run on the IO thread.
368 262
369 void SaveFileManager::OnSaveURL(const GURL& url, 263 void SaveFileManager::OnSaveURL(const GURL& url,
370 const Referrer& referrer, 264 const Referrer& referrer,
265 int save_item_id,
371 int save_package_id, 266 int save_package_id,
372 int render_process_host_id, 267 int render_process_host_id,
373 int render_view_routing_id, 268 int render_view_routing_id,
374 int render_frame_routing_id, 269 int render_frame_routing_id,
375 ResourceContext* context) { 270 ResourceContext* context) {
376 DCHECK_CURRENTLY_ON(BrowserThread::IO); 271 DCHECK_CURRENTLY_ON(BrowserThread::IO);
377 ResourceDispatcherHostImpl::Get()->BeginSaveFile( 272 ResourceDispatcherHostImpl::Get()->BeginSaveFile(
378 url, referrer, save_package_id, render_process_host_id, 273 url, referrer, save_item_id, save_package_id, render_process_host_id,
379 render_view_routing_id, render_frame_routing_id, context); 274 render_view_routing_id, render_frame_routing_id, context);
380 } 275 }
381 276
382 void SaveFileManager::OnRequireSaveJobFromOtherSource(
383 SaveFileCreateInfo* info) {
384 DCHECK_CURRENTLY_ON(BrowserThread::IO);
385 DCHECK_EQ(info->save_id, -1);
386 // Generate a unique save id.
387 info->save_id = GetNextId();
388 // Start real saving action.
389 BrowserThread::PostTask(
390 BrowserThread::FILE, FROM_HERE,
391 base::Bind(&SaveFileManager::StartSave, this, info));
392 }
393
394 void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id, 277 void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id,
395 int request_id) { 278 int request_id) {
396 DCHECK_CURRENTLY_ON(BrowserThread::IO); 279 DCHECK_CURRENTLY_ON(BrowserThread::IO);
397 ResourceDispatcherHostImpl::Get()->CancelRequest( 280 ResourceDispatcherHostImpl::Get()->CancelRequest(
398 render_process_id, request_id); 281 render_process_id, request_id);
399 } 282 }
400 283
401 // Notifications sent from the UI thread and run on the file thread. 284 // Notifications sent from the UI thread and run on the file thread.
402 285
403 // This method will be sent via a user action, or shutdown on the UI thread, 286 // This method will be sent via a user action, or shutdown on the UI thread,
404 // and run on the file thread. We don't post a message back for cancels, 287 // and run on the file thread. We don't post a message back for cancels,
405 // but we do forward the cancel to the IO thread. Since this message has been 288 // but we do forward the cancel to the IO thread. Since this message has been
406 // sent from the UI thread, the saving job may have already completed and 289 // sent from the UI thread, the saving job may have already completed and
407 // won't exist in our map. 290 // won't exist in our map.
408 void SaveFileManager::CancelSave(int save_id) { 291 void SaveFileManager::CancelSave(int save_item_id) {
409 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 292 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
410 SaveFileMap::iterator it = save_file_map_.find(save_id); 293 SaveFileMap::iterator it = save_file_map_.find(save_item_id);
411 if (it != save_file_map_.end()) { 294 if (it != save_file_map_.end()) {
412 SaveFile* save_file = it->second; 295 SaveFile* save_file = it->second;
413 296
414 if (!save_file->InProgress()) { 297 if (!save_file->InProgress()) {
415 // We've won a race with the UI thread--we finished the file before 298 // We've won a race with the UI thread--we finished the file before
416 // the UI thread cancelled it on us. Unfortunately, in this situation 299 // the UI thread cancelled it on us. Unfortunately, in this situation
417 // the cancel wins, so we need to delete the now detached file. 300 // the cancel wins, so we need to delete the now detached file.
418 base::DeleteFile(save_file->FullPath(), false); 301 base::DeleteFile(save_file->FullPath(), false);
419 } else if (save_file->save_source() == 302 } else if (save_file->save_source() ==
420 SaveFileCreateInfo::SAVE_FILE_FROM_NET) { 303 SaveFileCreateInfo::SAVE_FILE_FROM_NET) {
421 // If the data comes from the net IO thread and hasn't completed 304 // If the data comes from the net IO thread and hasn't completed
422 // yet, then forward the cancel message to IO thread & cancel the 305 // yet, then forward the cancel message to IO thread & cancel the
423 // save locally. If the data doesn't come from the IO thread, 306 // save locally. If the data doesn't come from the IO thread,
424 // we can ignore the message. 307 // we can ignore the message.
425 BrowserThread::PostTask( 308 BrowserThread::PostTask(
426 BrowserThread::IO, FROM_HERE, 309 BrowserThread::IO, FROM_HERE,
427 base::Bind(&SaveFileManager::ExecuteCancelSaveRequest, this, 310 base::Bind(&SaveFileManager::ExecuteCancelSaveRequest, this,
428 save_file->render_process_id(), save_file->request_id())); 311 save_file->render_process_id(), save_file->request_id()));
429 } 312 }
430 313
431 // Whatever the save file is complete or not, just delete it. This 314 // Whatever the save file is complete or not, just delete it. This
432 // will delete the underlying file if InProgress() is true. 315 // will delete the underlying file if InProgress() is true.
433 save_file_map_.erase(it); 316 save_file_map_.erase(it);
434 delete save_file; 317 delete save_file;
435 } 318 }
436 } 319 }
437 320
438 // It is possible that SaveItem which has specified save_id has been canceled 321 // It is possible that SaveItem which has specified save_item_id has been
322 // canceled
439 // before this function runs. So if we can not find corresponding SaveFile by 323 // before this function runs. So if we can not find corresponding SaveFile by
440 // using specified save_id, just return. 324 // using specified save_item_id, just return.
441 void SaveFileManager::SaveLocalFile(const GURL& original_file_url, 325 void SaveFileManager::SaveLocalFile(const GURL& original_file_url,
442 int save_id, 326 int save_item_id,
443 int save_package_id) { 327 int save_package_id) {
444 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 328 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
445 SaveFile* save_file = LookupSaveFile(save_id); 329 SaveFile* save_file = LookupSaveFile(save_item_id);
446 if (!save_file) 330 if (!save_file)
447 return; 331 return;
448 // If it has finished, just return. 332 // If it has finished, just return.
449 if (!save_file->InProgress()) 333 if (!save_file->InProgress())
450 return; 334 return;
451 335
452 // Close the save file before the copy operation. 336 // Close the save file before the copy operation.
453 save_file->Finish(); 337 save_file->Finish();
454 save_file->Detach(); 338 save_file->Detach();
455 339
456 DCHECK(original_file_url.SchemeIsFile()); 340 DCHECK(original_file_url.SchemeIsFile());
457 base::FilePath file_path; 341 base::FilePath file_path;
458 net::FileURLToFilePath(original_file_url, &file_path); 342 net::FileURLToFilePath(original_file_url, &file_path);
459 // If we can not get valid file path from original URL, treat it as 343 // If we can not get valid file path from original URL, treat it as
460 // disk error. 344 // disk error.
461 if (file_path.empty()) 345 if (file_path.empty())
462 SaveFinished(save_id, original_file_url, save_package_id, false); 346 SaveFinished(save_item_id, save_package_id, false);
463 347
464 // Copy the local file to the temporary file. It will be renamed to its 348 // Copy the local file to the temporary file. It will be renamed to its
465 // final name later. 349 // final name later.
466 bool success = base::CopyFile(file_path, save_file->FullPath()); 350 bool success = base::CopyFile(file_path, save_file->FullPath());
467 if (!success) 351 if (!success)
468 base::DeleteFile(save_file->FullPath(), false); 352 base::DeleteFile(save_file->FullPath(), false);
469 SaveFinished(save_id, original_file_url, save_package_id, success); 353 SaveFinished(save_item_id, save_package_id, success);
470 } 354 }
471 355
472 void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path, 356 void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path,
473 bool is_dir) { 357 bool is_dir) {
474 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 358 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
475 DCHECK(!full_path.empty()); 359 DCHECK(!full_path.empty());
476 360
477 base::DeleteFile(full_path, is_dir); 361 base::DeleteFile(full_path, is_dir);
478 } 362 }
479 363
480 void SaveFileManager::RenameAllFiles(const FinalNameList& final_names, 364 void SaveFileManager::RenameAllFiles(const FinalNamesMap& final_names,
481 const base::FilePath& resource_dir, 365 const base::FilePath& resource_dir,
482 int render_process_id, 366 int render_process_id,
483 int render_frame_routing_id, 367 int render_frame_routing_id,
484 int save_package_id) { 368 int save_package_id) {
485 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 369 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
486 370
487 if (!resource_dir.empty() && !base::PathExists(resource_dir)) 371 if (!resource_dir.empty() && !base::PathExists(resource_dir))
488 base::CreateDirectory(resource_dir); 372 base::CreateDirectory(resource_dir);
489 373
490 for (FinalNameList::const_iterator i = final_names.begin(); 374 for (const auto& i : final_names) {
491 i != final_names.end(); ++i) { 375 int save_item_id = i.first;
492 SaveFileMap::iterator it = save_file_map_.find(i->first); 376 const base::FilePath& final_name = i.second;
377
378 SaveFileMap::iterator it = save_file_map_.find(save_item_id);
493 if (it != save_file_map_.end()) { 379 if (it != save_file_map_.end()) {
494 SaveFile* save_file = it->second; 380 SaveFile* save_file = it->second;
495 DCHECK(!save_file->InProgress()); 381 DCHECK(!save_file->InProgress());
496 save_file->Rename(i->second); 382 save_file->Rename(final_name);
497 delete save_file; 383 delete save_file;
498 save_file_map_.erase(it); 384 save_file_map_.erase(it);
499 } 385 }
500 } 386 }
501 387
502 BrowserThread::PostTask( 388 BrowserThread::PostTask(
503 BrowserThread::UI, FROM_HERE, 389 BrowserThread::UI, FROM_HERE,
504 base::Bind(&SaveFileManager::OnFinishSavePageJob, this, render_process_id, 390 base::Bind(&SaveFileManager::OnFinishSavePageJob, this, render_process_id,
505 render_frame_routing_id, save_package_id)); 391 render_frame_routing_id, save_package_id));
506 } 392 }
507 393
508 void SaveFileManager::OnFinishSavePageJob(int render_process_id, 394 void SaveFileManager::OnFinishSavePageJob(int render_process_id,
509 int render_frame_routing_id, 395 int render_frame_routing_id,
510 int save_package_id) { 396 int save_package_id) {
511 DCHECK_CURRENTLY_ON(BrowserThread::UI); 397 DCHECK_CURRENTLY_ON(BrowserThread::UI);
512 398
513 SavePackage* save_package = 399 SavePackage* save_package =
514 GetSavePackageFromRenderIds(render_process_id, render_frame_routing_id); 400 GetSavePackageFromRenderIds(render_process_id, render_frame_routing_id);
515 401
516 if (save_package && save_package->id() == save_package_id) 402 if (save_package && save_package->id() == save_package_id)
517 save_package->Finish(); 403 save_package->Finish();
518 } 404 }
519 405
520 void SaveFileManager::RemoveSavedFileFromFileMap( 406 void SaveFileManager::RemoveSavedFileFromFileMap(
521 const SaveIDList& save_ids) { 407 const std::vector<int>& save_item_ids) {
522 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 408 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
523 409
524 for (SaveIDList::const_iterator i = save_ids.begin(); 410 for (const int save_item_id : save_item_ids) {
525 i != save_ids.end(); ++i) { 411 SaveFileMap::iterator it = save_file_map_.find(save_item_id);
526 SaveFileMap::iterator it = save_file_map_.find(*i);
527 if (it != save_file_map_.end()) { 412 if (it != save_file_map_.end()) {
528 SaveFile* save_file = it->second; 413 SaveFile* save_file = it->second;
529 DCHECK(!save_file->InProgress()); 414 DCHECK(!save_file->InProgress());
530 base::DeleteFile(save_file->FullPath(), false); 415 base::DeleteFile(save_file->FullPath(), false);
531 delete save_file; 416 delete save_file;
532 save_file_map_.erase(it); 417 save_file_map_.erase(it);
533 } 418 }
534 } 419 }
535 } 420 }
536 421
537 } // namespace content 422 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/save_file_manager.h ('k') | content/browser/download/save_file_resource_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698