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 |