| 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/save_package.h" | 5 #include "content/browser/download/save_package.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/file_path.h" | 10 #include "base/file_path.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 #endif | 72 #endif |
| 73 | 73 |
| 74 // Maximum length for file ordinal number part. Since we only support the | 74 // Maximum length for file ordinal number part. Since we only support the |
| 75 // maximum 9999 for ordinal number, which means maximum file ordinal number part | 75 // maximum 9999 for ordinal number, which means maximum file ordinal number part |
| 76 // should be "(9998)", so the value is 6. | 76 // should be "(9998)", so the value is 6. |
| 77 const uint32 kMaxFileOrdinalNumberPartLength = 6; | 77 const uint32 kMaxFileOrdinalNumberPartLength = 6; |
| 78 | 78 |
| 79 // Strip current ordinal number, if any. Should only be used on pure | 79 // Strip current ordinal number, if any. Should only be used on pure |
| 80 // file names, i.e. those stripped of their extensions. | 80 // file names, i.e. those stripped of their extensions. |
| 81 // TODO(estade): improve this to not choke on alternate encodings. | 81 // TODO(estade): improve this to not choke on alternate encodings. |
| 82 FilePath::StringType StripOrdinalNumber( | 82 base::FilePath::StringType StripOrdinalNumber( |
| 83 const FilePath::StringType& pure_file_name) { | 83 const base::FilePath::StringType& pure_file_name) { |
| 84 FilePath::StringType::size_type r_paren_index = | 84 base::FilePath::StringType::size_type r_paren_index = |
| 85 pure_file_name.rfind(FILE_PATH_LITERAL(')')); | 85 pure_file_name.rfind(FILE_PATH_LITERAL(')')); |
| 86 FilePath::StringType::size_type l_paren_index = | 86 base::FilePath::StringType::size_type l_paren_index = |
| 87 pure_file_name.rfind(FILE_PATH_LITERAL('(')); | 87 pure_file_name.rfind(FILE_PATH_LITERAL('(')); |
| 88 if (l_paren_index >= r_paren_index) | 88 if (l_paren_index >= r_paren_index) |
| 89 return pure_file_name; | 89 return pure_file_name; |
| 90 | 90 |
| 91 for (FilePath::StringType::size_type i = l_paren_index + 1; | 91 for (base::FilePath::StringType::size_type i = l_paren_index + 1; |
| 92 i != r_paren_index; ++i) { | 92 i != r_paren_index; ++i) { |
| 93 if (!IsAsciiDigit(pure_file_name[i])) | 93 if (!IsAsciiDigit(pure_file_name[i])) |
| 94 return pure_file_name; | 94 return pure_file_name; |
| 95 } | 95 } |
| 96 | 96 |
| 97 return pure_file_name.substr(0, l_paren_index); | 97 return pure_file_name.substr(0, l_paren_index); |
| 98 } | 98 } |
| 99 | 99 |
| 100 // Check whether we can save page as complete-HTML for the contents which | 100 // Check whether we can save page as complete-HTML for the contents which |
| 101 // have specified a MIME type. Now only contents which have the MIME type | 101 // have specified a MIME type. Now only contents which have the MIME type |
| 102 // "text/html" can be saved as complete-HTML. | 102 // "text/html" can be saved as complete-HTML. |
| 103 bool CanSaveAsComplete(const std::string& contents_mime_type) { | 103 bool CanSaveAsComplete(const std::string& contents_mime_type) { |
| 104 return contents_mime_type == "text/html" || | 104 return contents_mime_type == "text/html" || |
| 105 contents_mime_type == "application/xhtml+xml"; | 105 contents_mime_type == "application/xhtml+xml"; |
| 106 } | 106 } |
| 107 | 107 |
| 108 } // namespace | 108 } // namespace |
| 109 | 109 |
| 110 const FilePath::CharType SavePackage::kDefaultHtmlExtension[] = | 110 const base::FilePath::CharType SavePackage::kDefaultHtmlExtension[] = |
| 111 #if defined(OS_WIN) | 111 #if defined(OS_WIN) |
| 112 FILE_PATH_LITERAL("htm"); | 112 FILE_PATH_LITERAL("htm"); |
| 113 #else | 113 #else |
| 114 FILE_PATH_LITERAL("html"); | 114 FILE_PATH_LITERAL("html"); |
| 115 #endif | 115 #endif |
| 116 | 116 |
| 117 SavePackage::SavePackage(WebContents* web_contents, | 117 SavePackage::SavePackage(WebContents* web_contents, |
| 118 SavePageType save_type, | 118 SavePageType save_type, |
| 119 const FilePath& file_full_path, | 119 const base::FilePath& file_full_path, |
| 120 const FilePath& directory_full_path) | 120 const base::FilePath& directory_full_path) |
| 121 : WebContentsObserver(web_contents), | 121 : WebContentsObserver(web_contents), |
| 122 file_manager_(NULL), | 122 file_manager_(NULL), |
| 123 download_manager_(NULL), | 123 download_manager_(NULL), |
| 124 download_(NULL), | 124 download_(NULL), |
| 125 page_url_(GetUrlToBeSaved()), | 125 page_url_(GetUrlToBeSaved()), |
| 126 saved_main_file_path_(file_full_path), | 126 saved_main_file_path_(file_full_path), |
| 127 saved_main_directory_path_(directory_full_path), | 127 saved_main_directory_path_(directory_full_path), |
| 128 title_(web_contents->GetTitle()), | 128 title_(web_contents->GetTitle()), |
| 129 start_tick_(base::TimeTicks::Now()), | 129 start_tick_(base::TimeTicks::Now()), |
| 130 finished_(false), | 130 finished_(false), |
| 131 mhtml_finishing_(false), | 131 mhtml_finishing_(false), |
| 132 user_canceled_(false), | 132 user_canceled_(false), |
| 133 disk_error_occurred_(false), | 133 disk_error_occurred_(false), |
| 134 save_type_(save_type), | 134 save_type_(save_type), |
| 135 all_save_items_count_(0), | 135 all_save_items_count_(0), |
| 136 file_name_set_(&FilePath::CompareLessIgnoreCase), | 136 file_name_set_(&base::FilePath::CompareLessIgnoreCase), |
| 137 wait_state_(INITIALIZE), | 137 wait_state_(INITIALIZE), |
| 138 contents_id_(web_contents->GetRenderProcessHost()->GetID()), | 138 contents_id_(web_contents->GetRenderProcessHost()->GetID()), |
| 139 unique_id_(g_save_package_id++), | 139 unique_id_(g_save_package_id++), |
| 140 wrote_to_completed_file_(false), | 140 wrote_to_completed_file_(false), |
| 141 wrote_to_failed_file_(false) { | 141 wrote_to_failed_file_(false) { |
| 142 DCHECK(page_url_.is_valid()); | 142 DCHECK(page_url_.is_valid()); |
| 143 DCHECK((save_type_ == SAVE_PAGE_TYPE_AS_ONLY_HTML) || | 143 DCHECK((save_type_ == SAVE_PAGE_TYPE_AS_ONLY_HTML) || |
| 144 (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) || | 144 (save_type_ == SAVE_PAGE_TYPE_AS_MHTML) || |
| 145 (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML)); | 145 (save_type_ == SAVE_PAGE_TYPE_AS_COMPLETE_HTML)); |
| 146 DCHECK(!saved_main_file_path_.empty() && | 146 DCHECK(!saved_main_file_path_.empty() && |
| (...skipping 10 matching lines...) Expand all Loading... |
| 157 download_(NULL), | 157 download_(NULL), |
| 158 page_url_(GetUrlToBeSaved()), | 158 page_url_(GetUrlToBeSaved()), |
| 159 title_(web_contents->GetTitle()), | 159 title_(web_contents->GetTitle()), |
| 160 start_tick_(base::TimeTicks::Now()), | 160 start_tick_(base::TimeTicks::Now()), |
| 161 finished_(false), | 161 finished_(false), |
| 162 mhtml_finishing_(false), | 162 mhtml_finishing_(false), |
| 163 user_canceled_(false), | 163 user_canceled_(false), |
| 164 disk_error_occurred_(false), | 164 disk_error_occurred_(false), |
| 165 save_type_(SAVE_PAGE_TYPE_UNKNOWN), | 165 save_type_(SAVE_PAGE_TYPE_UNKNOWN), |
| 166 all_save_items_count_(0), | 166 all_save_items_count_(0), |
| 167 file_name_set_(&FilePath::CompareLessIgnoreCase), | 167 file_name_set_(&base::FilePath::CompareLessIgnoreCase), |
| 168 wait_state_(INITIALIZE), | 168 wait_state_(INITIALIZE), |
| 169 contents_id_(web_contents->GetRenderProcessHost()->GetID()), | 169 contents_id_(web_contents->GetRenderProcessHost()->GetID()), |
| 170 unique_id_(g_save_package_id++), | 170 unique_id_(g_save_package_id++), |
| 171 wrote_to_completed_file_(false), | 171 wrote_to_completed_file_(false), |
| 172 wrote_to_failed_file_(false) { | 172 wrote_to_failed_file_(false) { |
| 173 DCHECK(page_url_.is_valid()); | 173 DCHECK(page_url_.is_valid()); |
| 174 InternalInit(); | 174 InternalInit(); |
| 175 } | 175 } |
| 176 | 176 |
| 177 // This is for testing use. Set |finished_| as true because we don't want | 177 // This is for testing use. Set |finished_| as true because we don't want |
| 178 // method Cancel to be be called in destructor in test mode. | 178 // method Cancel to be be called in destructor in test mode. |
| 179 // We also don't call InternalInit(). | 179 // We also don't call InternalInit(). |
| 180 SavePackage::SavePackage(WebContents* web_contents, | 180 SavePackage::SavePackage(WebContents* web_contents, |
| 181 const FilePath& file_full_path, | 181 const base::FilePath& file_full_path, |
| 182 const FilePath& directory_full_path) | 182 const base::FilePath& directory_full_path) |
| 183 : WebContentsObserver(web_contents), | 183 : WebContentsObserver(web_contents), |
| 184 file_manager_(NULL), | 184 file_manager_(NULL), |
| 185 download_manager_(NULL), | 185 download_manager_(NULL), |
| 186 download_(NULL), | 186 download_(NULL), |
| 187 saved_main_file_path_(file_full_path), | 187 saved_main_file_path_(file_full_path), |
| 188 saved_main_directory_path_(directory_full_path), | 188 saved_main_directory_path_(directory_full_path), |
| 189 start_tick_(base::TimeTicks::Now()), | 189 start_tick_(base::TimeTicks::Now()), |
| 190 finished_(true), | 190 finished_(true), |
| 191 mhtml_finishing_(false), | 191 mhtml_finishing_(false), |
| 192 user_canceled_(false), | 192 user_canceled_(false), |
| 193 disk_error_occurred_(false), | 193 disk_error_occurred_(false), |
| 194 save_type_(SAVE_PAGE_TYPE_UNKNOWN), | 194 save_type_(SAVE_PAGE_TYPE_UNKNOWN), |
| 195 all_save_items_count_(0), | 195 all_save_items_count_(0), |
| 196 file_name_set_(&FilePath::CompareLessIgnoreCase), | 196 file_name_set_(&base::FilePath::CompareLessIgnoreCase), |
| 197 wait_state_(INITIALIZE), | 197 wait_state_(INITIALIZE), |
| 198 contents_id_(0), | 198 contents_id_(0), |
| 199 unique_id_(g_save_package_id++), | 199 unique_id_(g_save_package_id++), |
| 200 wrote_to_completed_file_(false), | 200 wrote_to_completed_file_(false), |
| 201 wrote_to_failed_file_(false) { | 201 wrote_to_failed_file_(false) { |
| 202 } | 202 } |
| 203 | 203 |
| 204 SavePackage::~SavePackage() { | 204 SavePackage::~SavePackage() { |
| 205 // Stop receiving saving job's updates | 205 // Stop receiving saving job's updates |
| 206 if (!finished_ && !canceled()) { | 206 if (!finished_ && !canceled()) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 waiting_item_queue_.push(save_item); | 317 waiting_item_queue_.push(save_item); |
| 318 all_save_items_count_ = 1; | 318 all_save_items_count_ = 1; |
| 319 download_->SetTotalBytes(1); | 319 download_->SetTotalBytes(1); |
| 320 | 320 |
| 321 DoSavingProcess(); | 321 DoSavingProcess(); |
| 322 } | 322 } |
| 323 | 323 |
| 324 return true; | 324 return true; |
| 325 } | 325 } |
| 326 | 326 |
| 327 void SavePackage::OnMHTMLGenerated(const FilePath& path, int64 size) { | 327 void SavePackage::OnMHTMLGenerated(const base::FilePath& path, int64 size) { |
| 328 if (size <= 0) { | 328 if (size <= 0) { |
| 329 Cancel(false); | 329 Cancel(false); |
| 330 return; | 330 return; |
| 331 } | 331 } |
| 332 wrote_to_completed_file_ = true; | 332 wrote_to_completed_file_ = true; |
| 333 | 333 |
| 334 // Hack to avoid touching download_ after user cancel. | 334 // Hack to avoid touching download_ after user cancel. |
| 335 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem | 335 // TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem |
| 336 // with SavePackage flow. | 336 // with SavePackage flow. |
| 337 if (download_->IsInProgress()) { | 337 if (download_->IsInProgress()) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 350 | 350 |
| 351 if (download_manager_->GetDelegate()->ShouldCompleteDownload( | 351 if (download_manager_->GetDelegate()->ShouldCompleteDownload( |
| 352 download_, base::Bind(&SavePackage::Finish, this))) { | 352 download_, base::Bind(&SavePackage::Finish, this))) { |
| 353 Finish(); | 353 Finish(); |
| 354 } | 354 } |
| 355 } | 355 } |
| 356 | 356 |
| 357 // On POSIX, the length of |pure_file_name| + |file_name_ext| is further | 357 // On POSIX, the length of |pure_file_name| + |file_name_ext| is further |
| 358 // restricted by NAME_MAX. The maximum allowed path looks like: | 358 // restricted by NAME_MAX. The maximum allowed path looks like: |
| 359 // '/path/to/save_dir' + '/' + NAME_MAX. | 359 // '/path/to/save_dir' + '/' + NAME_MAX. |
| 360 uint32 SavePackage::GetMaxPathLengthForDirectory(const FilePath& base_dir) { | 360 uint32 SavePackage::GetMaxPathLengthForDirectory( |
| 361 const base::FilePath& base_dir) { |
| 361 #if defined(OS_POSIX) | 362 #if defined(OS_POSIX) |
| 362 return std::min(kMaxFilePathLength, | 363 return std::min(kMaxFilePathLength, |
| 363 static_cast<uint32>(base_dir.value().length()) + | 364 static_cast<uint32>(base_dir.value().length()) + |
| 364 NAME_MAX + 1); | 365 NAME_MAX + 1); |
| 365 #else | 366 #else |
| 366 return kMaxFilePathLength; | 367 return kMaxFilePathLength; |
| 367 #endif | 368 #endif |
| 368 } | 369 } |
| 369 | 370 |
| 370 // File name is considered being consist of pure file name, dot and file | 371 // File name is considered being consist of pure file name, dot and file |
| (...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1390 | 1391 |
| 1391 void SavePackage::FinalizeDownloadEntry() { | 1392 void SavePackage::FinalizeDownloadEntry() { |
| 1392 DCHECK(download_); | 1393 DCHECK(download_); |
| 1393 DCHECK(download_manager_); | 1394 DCHECK(download_manager_); |
| 1394 | 1395 |
| 1395 download_manager_->OnSavePackageSuccessfullyFinished(download_); | 1396 download_manager_->OnSavePackageSuccessfullyFinished(download_); |
| 1396 StopObservation(); | 1397 StopObservation(); |
| 1397 } | 1398 } |
| 1398 | 1399 |
| 1399 } // namespace content | 1400 } // namespace content |
| OLD | NEW |