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/base_file.h" | 5 #include "content/browser/download/base_file.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <cguid.h> | 8 #include <cguid.h> |
9 #include <objbase.h> | 9 #include <objbase.h> |
10 #include <shellapi.h> | 10 #include <shellapi.h> |
11 | 11 |
12 #include "base/files/file.h" | 12 #include "base/files/file.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/guid.h" | 14 #include "base/guid.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
18 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
| 19 #include "base/win/scoped_com_initializer.h" |
19 #include "content/browser/download/download_interrupt_reasons_impl.h" | 20 #include "content/browser/download/download_interrupt_reasons_impl.h" |
20 #include "content/browser/download/download_stats.h" | 21 #include "content/browser/download/download_stats.h" |
21 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
22 #include "net/log/net_log_event_type.h" | 23 #include "net/log/net_log_event_type.h" |
23 | 24 |
24 namespace content { | 25 namespace content { |
25 namespace { | 26 namespace { |
26 | 27 |
27 const int kAllSpecialShFileOperationCodes[] = { | 28 const int kAllSpecialShFileOperationCodes[] = { |
28 // Should be kept in sync with the case statement below. | 29 // Should be kept in sync with the case statement below. |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 | 290 |
290 } // namespace | 291 } // namespace |
291 | 292 |
292 // Renames a file using the SHFileOperation API to ensure that the target file | 293 // Renames a file using the SHFileOperation API to ensure that the target file |
293 // gets the correct default security descriptor in the new path. | 294 // gets the correct default security descriptor in the new path. |
294 // Returns a network error, or net::OK for success. | 295 // Returns a network error, or net::OK for success. |
295 DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions( | 296 DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions( |
296 const base::FilePath& new_path) { | 297 const base::FilePath& new_path) { |
297 base::ThreadRestrictions::AssertIOAllowed(); | 298 base::ThreadRestrictions::AssertIOAllowed(); |
298 | 299 |
| 300 // TODO(siggi): This is pretty awkward, but at least better than forcing |
| 301 // all downloads to a single-threaded COM sequence runner. |
| 302 base::win::ScopedCOMInitializer com_initializer; |
| 303 |
299 // The parameters to SHFileOperation must be terminated with 2 NULL chars. | 304 // The parameters to SHFileOperation must be terminated with 2 NULL chars. |
300 base::FilePath::StringType source = full_path_.value(); | 305 base::FilePath::StringType source = full_path_.value(); |
301 base::FilePath::StringType target = new_path.value(); | 306 base::FilePath::StringType target = new_path.value(); |
302 | 307 |
303 source.append(1, L'\0'); | 308 source.append(1, L'\0'); |
304 target.append(1, L'\0'); | 309 target.append(1, L'\0'); |
305 | 310 |
306 SHFILEOPSTRUCT move_info = {0}; | 311 SHFILEOPSTRUCT move_info = {0}; |
307 move_info.wFunc = FO_MOVE; | 312 move_info.wFunc = FO_MOVE; |
308 move_info.pFrom = source.c_str(); | 313 move_info.pFrom = source.c_str(); |
309 move_info.pTo = target.c_str(); | 314 move_info.pTo = target.c_str(); |
310 move_info.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | | 315 move_info.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | |
311 FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS; | 316 FOF_NOCONFIRMMKDIR | FOF_NOCOPYSECURITYATTRIBS; |
312 | 317 |
313 int result = SHFileOperation(&move_info); | 318 int result = SHFileOperation(&move_info); |
314 DownloadInterruptReason interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NONE; | 319 DownloadInterruptReason interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NONE; |
315 | 320 |
316 if (result == 0 && move_info.fAnyOperationsAborted) | 321 if (result == 0 && move_info.fAnyOperationsAborted) |
317 interrupt_reason = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; | 322 interrupt_reason = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; |
318 else if (result != 0) | 323 else if (result != 0) |
319 interrupt_reason = MapShFileOperationCodes(result); | 324 interrupt_reason = MapShFileOperationCodes(result); |
320 | 325 |
321 if (interrupt_reason != DOWNLOAD_INTERRUPT_REASON_NONE) | 326 if (interrupt_reason != DOWNLOAD_INTERRUPT_REASON_NONE) |
322 return LogInterruptReason("SHFileOperation", result, interrupt_reason); | 327 return LogInterruptReason("SHFileOperation", result, interrupt_reason); |
323 return interrupt_reason; | 328 return interrupt_reason; |
324 } | 329 } |
325 | 330 |
326 } // namespace content | 331 } // namespace content |
OLD | NEW |