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

Side by Side Diff: chrome/browser/download/save_package.cc

Issue 23004: Port some strings in download/save_package.cc (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 months 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 "chrome/browser/download/save_package.h" 5 #include "chrome/browser/download/save_package.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/path_service.h" 10 #include "base/path_service.h"
(...skipping 25 matching lines...) Expand all
36 #include "net/base/net_util.h" 36 #include "net/base/net_util.h"
37 #include "net/url_request/url_request_context.h" 37 #include "net/url_request/url_request_context.h"
38 #include "webkit/glue/dom_serializer_delegate.h" 38 #include "webkit/glue/dom_serializer_delegate.h"
39 39
40 #include "generated_resources.h" 40 #include "generated_resources.h"
41 41
42 using base::Time; 42 using base::Time;
43 43
44 namespace { 44 namespace {
45 45
46 const FilePath::CharType kLeftParen = FILE_PATH_LITERAL('(');
47 const FilePath::CharType kRightParen = FILE_PATH_LITERAL(')');
48
46 // Default name which will be used when we can not get proper name from 49 // Default name which will be used when we can not get proper name from
47 // resource URL. 50 // resource URL.
48 const wchar_t kDefaultSaveName[] = L"saved_resource"; 51 const wchar_t kDefaultSaveName[] = L"saved_resource";
49 52
50 // Maximum number of file ordinal number. I think it's big enough for resolving 53 // Maximum number of file ordinal number. I think it's big enough for resolving
51 // name-conflict files which has same base file name. 54 // name-conflict files which has same base file name.
52 const int32 kMaxFileOrdinalNumber = 9999; 55 const int32 kMaxFileOrdinalNumber = 9999;
53 56
54 // Maximum length for file path. Since Windows have MAX_PATH limitation for 57 // Maximum length for file path. Since Windows have MAX_PATH limitation for
55 // file path, we need to make sure length of file path of every saved file 58 // file path, we need to make sure length of file path of every saved file
56 // is less than MAX_PATH 59 // is less than MAX_PATH
57 const uint32 kMaxFilePathLength = MAX_PATH - 1; 60 const uint32 kMaxFilePathLength = MAX_PATH - 1;
58 61
59 // Maximum length for file ordinal number part. Since we only support the 62 // Maximum length for file ordinal number part. Since we only support the
60 // maximum 9999 for ordinal number, which means maximum file ordinal number part 63 // maximum 9999 for ordinal number, which means maximum file ordinal number part
61 // should be "(9998)", so the value is 6. 64 // should be "(9998)", so the value is 6.
62 const uint32 kMaxFileOrdinalNumberPartLength = 6; 65 const uint32 kMaxFileOrdinalNumberPartLength = 6;
63 66
64 // If false, we don't prompt the user as to where to save the file. This 67 // If false, we don't prompt the user as to where to save the file. This
65 // exists only for testing. 68 // exists only for testing.
66 bool g_should_prompt_for_filename = true; 69 bool g_should_prompt_for_filename = true;
67 70
71 // Strip current ordinal number, if any. Should only be used on pure
72 // file names, i.e. those stripped of their extensions.
73 // TODO(estade): improve this to not choke on alternate encodings.
74 FilePath::StringType StripOrdinalNumber(
75 const FilePath::StringType& pure_file_name) {
76 FilePath::StringType::size_type r_paren_index =
77 pure_file_name.rfind(FILE_PATH_LITERAL(')'));
78 FilePath::StringType::size_type l_paren_index =
79 pure_file_name.rfind(FILE_PATH_LITERAL('('));
80 if (l_paren_index >= r_paren_index)
81 return pure_file_name;
82
83 for (FilePath::StringType::size_type i = l_paren_index + 1;
84 i != r_paren_index; ++i) {
85 if (!IsAsciiDigit(pure_file_name[i]))
86 return pure_file_name;
87 }
88
89 return pure_file_name.substr(0, l_paren_index);
90 }
91
68 } // namespace 92 } // namespace
69 93
70 SavePackage::SavePackage(WebContents* web_content, 94 SavePackage::SavePackage(WebContents* web_content,
71 SavePackageType save_type, 95 SavePackageType save_type,
72 const std::wstring& file_full_path, 96 const FilePath& file_full_path,
73 const std::wstring& directory_full_path) 97 const FilePath& directory_full_path)
74 : web_contents_(web_content), 98 : web_contents_(web_content),
75 save_type_(save_type), 99 save_type_(save_type),
76 saved_main_file_path_(file_full_path), 100 saved_main_file_path_(file_full_path),
77 saved_main_directory_path_(directory_full_path), 101 saved_main_directory_path_(directory_full_path),
78 all_save_items_count_(0), 102 all_save_items_count_(0),
79 disk_error_occurred_(false), 103 disk_error_occurred_(false),
80 user_canceled_(false), 104 user_canceled_(false),
81 download_(NULL), 105 download_(NULL),
82 finished_(false), 106 finished_(false),
83 wait_state_(INITIALIZE), 107 wait_state_(INITIALIZE),
84 tab_id_(web_content->process()->host_id()) { 108 tab_id_(web_content->process()->host_id()) {
85 DCHECK(web_content); 109 DCHECK(web_content);
86 const GURL& current_page_url = web_contents_->GetURL(); 110 const GURL& current_page_url = web_contents_->GetURL();
87 DCHECK(current_page_url.is_valid()); 111 DCHECK(current_page_url.is_valid());
88 page_url_ = UTF8ToWide(current_page_url.spec()); 112 page_url_ = UTF8ToWide(current_page_url.spec());
89 DCHECK(save_type_ == SAVE_AS_ONLY_HTML || 113 DCHECK(save_type_ == SAVE_AS_ONLY_HTML ||
90 save_type_ == SAVE_AS_COMPLETE_HTML); 114 save_type_ == SAVE_AS_COMPLETE_HTML);
91 DCHECK(!saved_main_file_path_.empty() && 115 DCHECK(!saved_main_file_path_.empty() &&
92 saved_main_file_path_.length() <= kMaxFilePathLength); 116 saved_main_file_path_.value().length() <= kMaxFilePathLength);
93 DCHECK(!saved_main_directory_path_.empty() && 117 DCHECK(!saved_main_directory_path_.empty() &&
94 saved_main_directory_path_.length() < kMaxFilePathLength); 118 saved_main_directory_path_.value().length() < kMaxFilePathLength);
95 } 119 }
96 120
97 // This is for testing use. Set |finished_| as true because we don't want 121 // This is for testing use. Set |finished_| as true because we don't want
98 // method Cancel to be be called in destructor in test mode. 122 // method Cancel to be be called in destructor in test mode.
99 SavePackage::SavePackage(const wchar_t* file_full_path, 123 SavePackage::SavePackage(const FilePath::CharType* file_full_path,
100 const wchar_t* directory_full_path) 124 const FilePath::CharType* directory_full_path)
101 : all_save_items_count_(0), 125 : all_save_items_count_(0),
102 saved_main_file_path_(file_full_path), 126 saved_main_file_path_(file_full_path),
103 saved_main_directory_path_(directory_full_path), 127 saved_main_directory_path_(directory_full_path),
104 finished_(true), 128 finished_(true),
105 download_(NULL), 129 download_(NULL),
106 user_canceled_(false), 130 user_canceled_(false),
107 disk_error_occurred_(false), 131 disk_error_occurred_(false),
108 tab_id_(0) { 132 tab_id_(0) {
109 DCHECK(!saved_main_file_path_.empty() && 133 DCHECK(!saved_main_file_path_.empty() &&
110 saved_main_file_path_.length() <= kMaxFilePathLength); 134 saved_main_file_path_.value().length() <= kMaxFilePathLength);
111 DCHECK(!saved_main_directory_path_.empty() && 135 DCHECK(!saved_main_directory_path_.empty() &&
112 saved_main_directory_path_.length() < kMaxFilePathLength); 136 saved_main_directory_path_.value().length() < kMaxFilePathLength);
113 } 137 }
114 138
115 SavePackage::~SavePackage() { 139 SavePackage::~SavePackage() {
116 // Stop receiving saving job's updates 140 // Stop receiving saving job's updates
117 if (!finished_ && !canceled()) { 141 if (!finished_ && !canceled()) {
118 // Unexpected quit. 142 // Unexpected quit.
119 Cancel(true); 143 Cancel(true);
120 } 144 }
121 145
122 DCHECK(all_save_items_count_ == (waiting_item_queue_.size() + 146 DCHECK(all_save_items_count_ == (waiting_item_queue_.size() +
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 return false; 203 return false;
180 } 204 }
181 205
182 file_manager_ = rdh->save_file_manager(); 206 file_manager_ = rdh->save_file_manager();
183 if (!file_manager_) { 207 if (!file_manager_) {
184 NOTREACHED(); 208 NOTREACHED();
185 return false; 209 return false;
186 } 210 }
187 211
188 // Create the fake DownloadItem and display the view. 212 // Create the fake DownloadItem and display the view.
189 download_ = new DownloadItem(1, 213 download_ = new DownloadItem(1, saved_main_file_path_, 0, page_url_,
190 FilePath::FromWStringHack(saved_main_file_path_), 0, page_url_,
191 FilePath(), Time::Now(), 0, -1, -1, false); 214 FilePath(), Time::Now(), 0, -1, -1, false);
192 download_->set_manager(web_contents_->profile()->GetDownloadManager()); 215 download_->set_manager(web_contents_->profile()->GetDownloadManager());
193 DownloadShelfView* shelf = web_contents_->GetDownloadShelfView(); 216 DownloadShelfView* shelf = web_contents_->GetDownloadShelfView();
194 shelf->AddDownloadView(new DownloadItemView( 217 shelf->AddDownloadView(new DownloadItemView(
195 download_, shelf, new SavePageModel(this, download_))); 218 download_, shelf, new SavePageModel(this, download_)));
196 web_contents_->SetDownloadShelfVisible(true); 219 web_contents_->SetDownloadShelfVisible(true);
197 220
198 // Check save type and process the save page job. 221 // Check save type and process the save page job.
199 if (save_type_ == SAVE_AS_COMPLETE_HTML) { 222 if (save_type_ == SAVE_AS_COMPLETE_HTML) {
200 // Get directory 223 // Get directory
(...skipping 15 matching lines...) Expand all
216 download_->set_total_bytes(1); 239 download_->set_total_bytes(1);
217 240
218 DoSavingProcess(); 241 DoSavingProcess();
219 } 242 }
220 243
221 return true; 244 return true;
222 } 245 }
223 246
224 // Generate name for saving resource. 247 // Generate name for saving resource.
225 bool SavePackage::GenerateFilename(const std::string& disposition, 248 bool SavePackage::GenerateFilename(const std::string& disposition,
226 const std::wstring& url, 249 const GURL& url,
227 bool need_html_ext, 250 bool need_html_ext,
228 std::wstring* generated_name) { 251 FilePath::StringType* generated_name) {
229 std::wstring file_name = 252 FilePath file_path = FilePath::FromWStringHack(
230 net::GetSuggestedFilename(GURL(url), disposition, kDefaultSaveName); 253 net::GetSuggestedFilename(url, disposition, kDefaultSaveName));
231 254
232 DCHECK(!file_name.empty()); 255 DCHECK(!file_path.empty());
233 // Check whether we have same name before. 256 FilePath::StringType pure_file_name =
234 std::wstring::size_type last_dot = file_name.rfind(L'.'); 257 file_path.RemoveExtension().BaseName().value();
235 std::wstring pure_file_name, file_name_ext; 258 FilePath::StringType file_name_ext = file_path.Extension();
236 if (last_dot == std::wstring::npos) { 259
237 pure_file_name = file_name;
238 } else {
239 pure_file_name = std::wstring(file_name, 0, last_dot);
240 file_name_ext = std::wstring(file_name, last_dot);
241 }
242 // If it is HTML resource, use ".htm" as its extension name. 260 // If it is HTML resource, use ".htm" as its extension name.
243 if (need_html_ext) 261 if (need_html_ext)
244 file_name_ext = L".htm"; 262 file_name_ext = FILE_PATH_LITERAL(".htm");
245 if (file_name_ext == L".")
246 file_name_ext.clear();
247 263
248 // Get safe pure file name. 264 // Get safe pure file name.
249 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext, 265 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
250 kMaxFilePathLength, &pure_file_name)) 266 kMaxFilePathLength, &pure_file_name))
251 return false; 267 return false;
252 268
253 file_name = pure_file_name + file_name_ext; 269 FilePath::StringType file_name = pure_file_name + file_name_ext;
254 270
255 // Check whether we already have same name. 271 // Check whether we already have same name.
256 if (file_name_set_.find(file_name) == file_name_set_.end()) { 272 if (file_name_set_.find(file_name) == file_name_set_.end()) {
257 file_name_set_.insert(file_name); 273 file_name_set_.insert(file_name);
258 } else { 274 } else {
259 // Found same name, increase the ordinal number for the file name. 275 // Found same name, increase the ordinal number for the file name.
260 std::wstring base_file_name, file_ordinal_number; 276 FilePath::StringType base_file_name = StripOrdinalNumber(pure_file_name);
261
262 if (!GetBaseFileNameAndFileOrdinalNumber(pure_file_name, &base_file_name,
263 &file_ordinal_number))
264 base_file_name = pure_file_name;
265 277
266 // We need to make sure the length of base file name plus maximum ordinal 278 // We need to make sure the length of base file name plus maximum ordinal
267 // number path will be less than or equal to kMaxFilePathLength. 279 // number path will be less than or equal to kMaxFilePathLength.
268 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext, 280 if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
269 kMaxFilePathLength - kMaxFileOrdinalNumberPartLength, &base_file_name)) 281 kMaxFilePathLength - kMaxFileOrdinalNumberPartLength, &base_file_name))
270 return false; 282 return false;
271 283
272 // Prepare the new ordinal number. 284 // Prepare the new ordinal number.
273 uint32 ordinal_number; 285 uint32 ordinal_number;
274 FileNameCountMap::iterator it = file_name_count_map_.find(base_file_name); 286 FileNameCountMap::iterator it = file_name_count_map_.find(base_file_name);
275 if (it == file_name_count_map_.end()) { 287 if (it == file_name_count_map_.end()) {
276 // First base-name-conflict resolving, use 1 as initial ordinal number. 288 // First base-name-conflict resolving, use 1 as initial ordinal number.
277 file_name_count_map_[base_file_name] = 1; 289 file_name_count_map_[base_file_name] = 1;
278 ordinal_number = 1; 290 ordinal_number = 1;
279 } else { 291 } else {
280 // We have met same base-name conflict, use latest ordinal number. 292 // We have met same base-name conflict, use latest ordinal number.
281 ordinal_number = it->second; 293 ordinal_number = it->second;
282 } 294 }
283 295
284 if (ordinal_number > (kMaxFileOrdinalNumber - 1)) { 296 if (ordinal_number > (kMaxFileOrdinalNumber - 1)) {
285 // Use a random file from temporary file. 297 // Use a random file from temporary file.
286 file_util::CreateTemporaryFileName(&file_name); 298 FilePath temp_file;
287 file_name = file_util::GetFilenameFromPath(file_name); 299 file_util::CreateTemporaryFileName(&temp_file);
300 file_name = temp_file.RemoveExtension().BaseName().value();
288 // Get safe pure file name. 301 // Get safe pure file name.
289 if (!GetSafePureFileName(saved_main_directory_path_, std::wstring(), 302 if (!GetSafePureFileName(saved_main_directory_path_,
303 FilePath::StringType(),
290 kMaxFilePathLength, &file_name)) 304 kMaxFilePathLength, &file_name))
291 return false; 305 return false;
292 } else { 306 } else {
293 uint32 i; 307 uint32 i;
294 for (i = ordinal_number; i < kMaxFileOrdinalNumber; ++i) { 308 for (i = ordinal_number; i < kMaxFileOrdinalNumber; ++i) {
295 std::wstring new_name = 309 FilePath::StringType new_name = base_file_name +
296 StringPrintf(L"%ls(%d)", base_file_name.c_str(), i) + file_name_ext; 310 StringPrintf(FILE_PATH_LITERAL("(%d)"), i) + file_name_ext;
297 if (file_name_set_.find(new_name) == file_name_set_.end()) { 311 if (file_name_set_.find(new_name) == file_name_set_.end()) {
298 // Resolved name conflict. 312 // Resolved name conflict.
299 file_name = new_name; 313 file_name = new_name;
300 file_name_count_map_[base_file_name] = ++i; 314 file_name_count_map_[base_file_name] = ++i;
301 break; 315 break;
302 } 316 }
303 } 317 }
304 } 318 }
305 319
306 file_name_set_.insert(file_name); 320 file_name_set_.insert(file_name);
(...skipping 20 matching lines...) Expand all
327 341
328 DCHECK(!saved_main_file_path_.empty()); 342 DCHECK(!saved_main_file_path_.empty());
329 343
330 save_item->SetSaveId(info->save_id); 344 save_item->SetSaveId(info->save_id);
331 save_item->SetTotalBytes(info->total_bytes); 345 save_item->SetTotalBytes(info->total_bytes);
332 346
333 // Determine the proper path for a saving job, by choosing either the default 347 // Determine the proper path for a saving job, by choosing either the default
334 // save directory, or prompting the user. 348 // save directory, or prompting the user.
335 DCHECK(!save_item->has_final_name()); 349 DCHECK(!save_item->has_final_name());
336 if (info->url != page_url_) { 350 if (info->url != page_url_) {
337 std::wstring generated_name; 351 FilePath::StringType generated_name;
338 // For HTML resource file, make sure it will have .htm as extension name, 352 // For HTML resource file, make sure it will have .htm as extension name,
339 // otherwise, when you open the saved page in Chrome again, download 353 // otherwise, when you open the saved page in Chrome again, download
340 // file manager will treat it as downloadable resource, and download it 354 // file manager will treat it as downloadable resource, and download it
341 // instead of opening it as HTML. 355 // instead of opening it as HTML.
342 bool need_html_ext = 356 bool need_html_ext =
343 info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM; 357 info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM;
344 if (!GenerateFilename(info->content_disposition, 358 if (!GenerateFilename(info->content_disposition,
345 info->url, 359 GURL(info->url),
346 need_html_ext, 360 need_html_ext,
347 &generated_name)) { 361 &generated_name)) {
348 // We can not generate file name for this SaveItem, so we cancel the 362 // We can not generate file name for this SaveItem, so we cancel the
349 // saving page job if the save source is from serialized DOM data. 363 // saving page job if the save source is from serialized DOM data.
350 // Otherwise, it means this SaveItem is sub-resource type, we treat it 364 // Otherwise, it means this SaveItem is sub-resource type, we treat it
351 // as an error happened on saving. We can ignore this type error for 365 // as an error happened on saving. We can ignore this type error for
352 // sub-resource links which will be resolved as absolute links instead 366 // sub-resource links which will be resolved as absolute links instead
353 // of local links in final saved contents. 367 // of local links in final saved contents.
354 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM) 368 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM)
355 Cancel(true); 369 Cancel(true);
356 else 370 else
357 SaveFinished(save_item->save_id(), 0, false); 371 SaveFinished(save_item->save_id(), 0, false);
358 return; 372 return;
359 } 373 }
360 374
361 // When saving page as only-HTML, we only have a SaveItem whose url 375 // When saving page as only-HTML, we only have a SaveItem whose url
362 // must be page_url_. 376 // must be page_url_.
363 DCHECK(save_type_ == SAVE_AS_COMPLETE_HTML); 377 DCHECK(save_type_ == SAVE_AS_COMPLETE_HTML);
364 DCHECK(!saved_main_directory_path_.empty()); 378 DCHECK(!saved_main_directory_path_.empty());
365 379
366 // Now we get final name retrieved from GenerateFilename, we will use it 380 // Now we get final name retrieved from GenerateFilename, we will use it
367 // rename the SaveItem. 381 // rename the SaveItem.
368 std::wstring final_name = saved_main_directory_path_; 382 FilePath final_name = saved_main_directory_path_.Append(generated_name);
369 file_util::AppendToPath(&final_name, generated_name); 383 save_item->Rename(final_name.ToWStringHack());
370 save_item->Rename(final_name);
371 } else { 384 } else {
372 // It is the main HTML file, use the name chosen by the user. 385 // It is the main HTML file, use the name chosen by the user.
373 save_item->Rename(saved_main_file_path_); 386 save_item->Rename(saved_main_file_path_.ToWStringHack());
374 } 387 }
375 388
376 // If the save source is from file system, inform SaveFileManager to copy 389 // If the save source is from file system, inform SaveFileManager to copy
377 // corresponding file to the file path which this SaveItem specifies. 390 // corresponding file to the file path which this SaveItem specifies.
378 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) { 391 if (info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_FILE) {
379 file_manager_->GetSaveLoop()->PostTask(FROM_HERE, 392 file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
380 NewRunnableMethod(file_manager_, 393 NewRunnableMethod(file_manager_,
381 &SaveFileManager::SaveLocalFile, 394 &SaveFileManager::SaveLocalFile,
382 save_item->url(), 395 save_item->url(),
383 save_item->save_id(), 396 save_item->save_id(),
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 500
488 // Inform the DownloadItem we have canceled whole save page job. 501 // Inform the DownloadItem we have canceled whole save page job.
489 DCHECK(download_); 502 DCHECK(download_);
490 download_->Cancel(false); 503 download_->Cancel(false);
491 } 504 }
492 505
493 void SavePackage::CheckFinish() { 506 void SavePackage::CheckFinish() {
494 if (in_process_count() || finished_) 507 if (in_process_count() || finished_)
495 return; 508 return;
496 509
497 std::wstring dir = save_type_ == SAVE_AS_COMPLETE_HTML ? 510 FilePath dir = save_type_ == SAVE_AS_COMPLETE_HTML ?
498 saved_main_directory_path_ : 511 saved_main_directory_path_ :
499 L""; 512 FilePath();
500 513
501 // This vector contains the final names of all the successfully saved files 514 // This vector contains the final names of all the successfully saved files
502 // along with their save ids. It will be passed to SaveFileManager to do the 515 // along with their save ids. It will be passed to SaveFileManager to do the
503 // renaming job. 516 // renaming job.
504 FinalNameList final_names; 517 FinalNameList final_names;
505 for (SavedItemMap::iterator it = saved_success_items_.begin(); 518 for (SavedItemMap::iterator it = saved_success_items_.begin();
506 it != saved_success_items_.end(); ++it) 519 it != saved_success_items_.end(); ++it)
507 final_names.push_back(std::make_pair(it->first, 520 final_names.push_back(std::make_pair(it->first,
508 it->second->full_path())); 521 it->second->full_path()));
509 522
510 file_manager_->GetSaveLoop()->PostTask(FROM_HERE, 523 file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
511 NewRunnableMethod(file_manager_, 524 NewRunnableMethod(file_manager_,
512 &SaveFileManager::RenameAllFiles, 525 &SaveFileManager::RenameAllFiles,
513 final_names, 526 final_names,
514 dir, 527 dir.ToWStringHack(),
515 web_contents_->process()->host_id(), 528 web_contents_->process()->host_id(),
516 web_contents_->render_view_host()->routing_id())); 529 web_contents_->render_view_host()->routing_id()));
517 } 530 }
518 531
519 // Successfully finished all items of this SavePackage. 532 // Successfully finished all items of this SavePackage.
520 void SavePackage::Finish() { 533 void SavePackage::Finish() {
521 // User may cancel the job when we're moving files to the final directory. 534 // User may cancel the job when we're moving files to the final directory.
522 if (canceled()) 535 if (canceled())
523 return; 536 return;
524 537
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 677
665 678
666 // Open download page in windows explorer on file thread, to avoid blocking the 679 // Open download page in windows explorer on file thread, to avoid blocking the
667 // user interface. 680 // user interface.
668 void SavePackage::ShowDownloadInShell() { 681 void SavePackage::ShowDownloadInShell() {
669 DCHECK(file_manager_); 682 DCHECK(file_manager_);
670 DCHECK(finished_ && !canceled() && !saved_main_file_path_.empty()); 683 DCHECK(finished_ && !canceled() && !saved_main_file_path_.empty());
671 file_manager_->GetSaveLoop()->PostTask(FROM_HERE, 684 file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
672 NewRunnableMethod(file_manager_, 685 NewRunnableMethod(file_manager_,
673 &SaveFileManager::OnShowSavedFileInShell, 686 &SaveFileManager::OnShowSavedFileInShell,
674 saved_main_file_path_)); 687 saved_main_file_path_.ToWStringHack()));
675 } 688 }
676 689
677 // Calculate the percentage of whole save page job. 690 // Calculate the percentage of whole save page job.
678 int SavePackage::PercentComplete() { 691 int SavePackage::PercentComplete() {
679 if (!all_save_items_count_) 692 if (!all_save_items_count_)
680 return 0; 693 return 0;
681 else if (!in_process_count()) 694 else if (!in_process_count())
682 return 100; 695 return 100;
683 else 696 else
684 return completed_count() / all_save_items_count_; 697 return completed_count() / all_save_items_count_;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 769
757 // Collect all saved success items. 770 // Collect all saved success items.
758 for (SavedItemMap::iterator it = saved_success_items_.begin(); 771 for (SavedItemMap::iterator it = saved_success_items_.begin();
759 it != saved_success_items_.end(); ++it) { 772 it != saved_success_items_.end(); ++it) {
760 DCHECK(it->second->has_final_name()); 773 DCHECK(it->second->has_final_name());
761 saved_links.push_back(it->second->url()); 774 saved_links.push_back(it->second->url());
762 saved_file_paths.push_back(it->second->file_name()); 775 saved_file_paths.push_back(it->second->file_name());
763 } 776 }
764 777
765 // Get the relative directory name. 778 // Get the relative directory name.
766 std::wstring::size_type last_slash = saved_main_directory_path_.rfind(L'\\'); 779 FilePath relative_dir_name = saved_main_directory_path_.BaseName();
767 DCHECK(last_slash != std::wstring::npos);
768 std::wstring relative_dir_name = std::wstring(saved_main_directory_path_,
769 last_slash + 1);
770 780
771 relative_dir_name = std::wstring(L"./") + relative_dir_name + L"/"; 781 std::wstring relative_dir_name_str = std::wstring(L"./") +
782 relative_dir_name.ToWStringHack() + L"/";
772 783
773 web_contents_->render_view_host()-> 784 web_contents_->render_view_host()->
774 GetSerializedHtmlDataForCurrentPageWithLocalLinks( 785 GetSerializedHtmlDataForCurrentPageWithLocalLinks(
775 saved_links, saved_file_paths, relative_dir_name); 786 saved_links, saved_file_paths, relative_dir_name_str);
776 } 787 }
777 788
778 // Process the serialized HTML content data of a specified web page 789 // Process the serialized HTML content data of a specified web page
779 // retrieved from render process. 790 // retrieved from render process.
780 void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url, 791 void SavePackage::OnReceivedSerializedHtmlData(const GURL& frame_url,
781 const std::string& data, 792 const std::string& data,
782 int32 status) { 793 int32 status) {
783 webkit_glue::DomSerializerDelegate::PageSavingSerializationStatus flag = 794 webkit_glue::DomSerializerDelegate::PageSavingSerializationStatus flag =
784 static_cast<webkit_glue::DomSerializerDelegate::PageSavingSerializationSta tus> 795 static_cast<webkit_glue::DomSerializerDelegate::PageSavingSerializationSta tus>
785 (status); 796 (status);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 } else { 903 } else {
893 // No resource files need to be saved, treat it as user cancel. 904 // No resource files need to be saved, treat it as user cancel.
894 Cancel(true); 905 Cancel(true);
895 } 906 }
896 } 907 }
897 908
898 void SavePackage::SetShouldPromptUser(bool should_prompt) { 909 void SavePackage::SetShouldPromptUser(bool should_prompt) {
899 g_should_prompt_for_filename = should_prompt; 910 g_should_prompt_for_filename = should_prompt;
900 } 911 }
901 912
902 std::wstring SavePackage::GetSuggestNameForSaveAs(PrefService* prefs, 913 // static
903 const std::wstring& name) { 914 FilePath SavePackage::GetSuggestNameForSaveAs(PrefService* prefs,
915 const FilePath& name) {
904 // Check whether the preference has the preferred directory for saving file. 916 // Check whether the preference has the preferred directory for saving file.
905 // If not, initialize it with default directory. 917 // If not, initialize it with default directory.
906 if (!prefs->IsPrefRegistered(prefs::kSaveFileDefaultDirectory)) { 918 if (!prefs->IsPrefRegistered(prefs::kSaveFileDefaultDirectory)) {
907 std::wstring default_save_path; 919 FilePath default_save_path;
908 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, 920 if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS,
909 &default_save_path)) 921 &default_save_path))
910 NOTREACHED(); 922 NOTREACHED();
911 prefs->RegisterStringPref(prefs::kSaveFileDefaultDirectory, 923 prefs->RegisterStringPref(prefs::kSaveFileDefaultDirectory,
912 default_save_path); 924 default_save_path.ToWStringHack());
913 } 925 }
914 926
915 // Get the directory from preference. 927 // Get the directory from preference.
916 StringPrefMember save_file_path; 928 StringPrefMember save_file_path;
917 save_file_path.Init(prefs::kSaveFileDefaultDirectory, prefs, NULL); 929 save_file_path.Init(prefs::kSaveFileDefaultDirectory, prefs, NULL);
918 DCHECK(!(*save_file_path).empty()); 930 DCHECK(!(*save_file_path).empty());
919 931
920 // Ask user for getting final saving name. 932 // Ask user for getting final saving name.
921 std::wstring suggest_name, file_name; 933 std::wstring file_name = name.ToWStringHack();
922
923 file_name = name;
924 file_util::ReplaceIllegalCharacters(&file_name, L' '); 934 file_util::ReplaceIllegalCharacters(&file_name, L' ');
925 suggest_name = *save_file_path; 935 FilePath suggest_name = FilePath::FromWStringHack(save_file_path.GetValue());
926 file_util::AppendToPath(&suggest_name, file_name); 936 suggest_name = suggest_name.Append(file_name);
927 937
928 return suggest_name; 938 return suggest_name;
929 } 939 }
930 940
931 // Static. 941 // Static.
932 bool SavePackage::GetSaveInfo(const std::wstring& suggest_name, 942 bool SavePackage::GetSaveInfo(const FilePath& suggest_name,
933 HWND container_hwnd, 943 HWND container_hwnd,
934 SavePackageParam* param, 944 SavePackageParam* param,
935 DownloadManager* download_manager) { 945 DownloadManager* download_manager) {
936 // TODO(tc): It might be nice to move this code into the download 946 // TODO(tc): It might be nice to move this code into the download
937 // manager. http://crbug.com/6025 947 // manager. http://crbug.com/6025
938 948
939 // Use "Web Page, Complete" option as default choice of saving page. 949 // Use "Web Page, Complete" option as default choice of saving page.
940 unsigned index = 2; 950 unsigned index = 2;
941 951
942 // If the contents can not be saved as complete-HTML, do not show the 952 // If the contents can not be saved as complete-HTML, do not show the
943 // file filters. 953 // file filters.
944 if (CanSaveAsComplete(param->current_tab_mime_type)) { 954 if (CanSaveAsComplete(param->current_tab_mime_type)) {
945 // Create filter string. 955 // Create filter string.
946 std::wstring filter = l10n_util::GetString(IDS_SAVE_PAGE_FILTER); 956 std::wstring filter = l10n_util::GetString(IDS_SAVE_PAGE_FILTER);
947 filter.resize(filter.size() + 2); 957 filter.resize(filter.size() + 2);
948 filter[filter.size() - 1] = L'\0'; 958 filter[filter.size() - 1] = L'\0';
949 filter[filter.size() - 2] = L'\0'; 959 filter[filter.size() - 2] = L'\0';
950 960
951 if (g_should_prompt_for_filename) { 961 if (g_should_prompt_for_filename) {
952 // Since we take the suggested name from the web page's title, we want to 962 // Since we take the suggested name from the web page's title, we want to
953 // ignore the file extension generated by SaveFileAsWithFilter, since it 963 // ignore the file extension generated by SaveFileAsWithFilter, since it
954 // will always be ".htm". 964 // will always be ".htm".
965 // TODO(estade): is this saved_main_file_path assignment behavior desired?
966 // It was copied from previous code but seems strange.
967 std::wstring main_file_path;
955 if (!win_util::SaveFileAsWithFilter(container_hwnd, 968 if (!win_util::SaveFileAsWithFilter(container_hwnd,
956 suggest_name, 969 suggest_name.value(),
957 filter, 970 filter,
958 L"htm", 971 L"htm",
959 true, 972 true,
960 &index, 973 &index,
961 &param->saved_main_file_path)) 974 &main_file_path)) {
975 param->saved_main_file_path = FilePath(main_file_path);
962 return false; 976 return false;
977 }
963 } else { 978 } else {
964 param->saved_main_file_path = suggest_name; 979 param->saved_main_file_path = suggest_name;
965 } 980 }
966 } else { 981 } else {
967 if (g_should_prompt_for_filename) { 982 if (g_should_prompt_for_filename) {
968 if (!win_util::SaveFileAs(container_hwnd, suggest_name, 983 // TODO(estade): see above comment.
969 &param->saved_main_file_path)) 984 std::wstring main_file_path;
985 if (!win_util::SaveFileAs(container_hwnd, suggest_name.value(),
986 &main_file_path))
987 param->saved_main_file_path = FilePath(main_file_path);
970 return false; 988 return false;
971 } else { 989 } else {
972 param->saved_main_file_path = suggest_name; 990 param->saved_main_file_path = suggest_name;
973 } 991 }
974 // Set save-as type to only-HTML if the contents of current tab can not be 992 // Set save-as type to only-HTML if the contents of current tab can not be
975 // saved as complete-HTML. 993 // saved as complete-HTML.
976 index = 1; 994 index = 1;
977 } 995 }
978 996
979 DCHECK(download_manager); 997 DCHECK(download_manager);
980 // Ensure the filename is safe. 998 // Ensure the filename is safe.
981 FilePath path(param->saved_main_file_path); 999 download_manager->GenerateSafeFilename(param->current_tab_mime_type,
982 download_manager->GenerateSafeFilename(param->current_tab_mime_type, &path); 1000 &param->saved_main_file_path);
983 param->saved_main_file_path = path.ToWStringHack();
984 1001
985 // The option index is not zero-based. 1002 // The option index is not zero-based.
986 DCHECK(index > 0 && index < 3); 1003 DCHECK(index > 0 && index < 3);
987 param->dir = file_util::GetDirectoryFromPath(param->saved_main_file_path); 1004 param->dir = param->saved_main_file_path.DirName();
988 1005
989 StringPrefMember save_file_path; 1006 StringPrefMember save_file_path;
990 save_file_path.Init(prefs::kSaveFileDefaultDirectory, param->prefs, NULL); 1007 save_file_path.Init(prefs::kSaveFileDefaultDirectory, param->prefs, NULL);
991 // If user change the default saving directory, we will remember it just 1008 // If user change the default saving directory, we will remember it just
992 // like IE and FireFox. 1009 // like IE and FireFox.
993 if (save_file_path.GetValue() != param->dir) 1010 if (save_file_path.GetValue() != param->dir.ToWStringHack())
994 save_file_path.SetValue(param->dir); 1011 save_file_path.SetValue(param->dir.ToWStringHack());
995 1012
996 param->save_type = (index == 1) ? SavePackage::SAVE_AS_ONLY_HTML : 1013 param->save_type = (index == 1) ? SavePackage::SAVE_AS_ONLY_HTML :
997 SavePackage::SAVE_AS_COMPLETE_HTML; 1014 SavePackage::SAVE_AS_COMPLETE_HTML;
998 1015
999 if (param->save_type == SavePackage::SAVE_AS_COMPLETE_HTML) { 1016 if (param->save_type == SavePackage::SAVE_AS_COMPLETE_HTML) {
1000 // Make new directory for saving complete file. 1017 // Make new directory for saving complete file.
1001 std::wstring file_name = 1018 param->dir = param->dir.Append(
1002 file_util::GetFilenameFromPath(param->saved_main_file_path); 1019 param->saved_main_file_path.RemoveExtension().BaseName().value() +
1003 std::wstring::size_type last_dot = file_name.rfind(L'.'); 1020 FILE_PATH_LITERAL("_files"));
1004 std::wstring pure_file_name;
1005 if (last_dot == std::wstring::npos)
1006 pure_file_name = file_name;
1007 else
1008 pure_file_name = std::wstring(file_name, 0, last_dot);
1009 pure_file_name += L"_files";
1010 file_util::AppendToPath(&param->dir, pure_file_name);
1011 } 1021 }
1012 1022
1013 return true; 1023 return true;
1014 } 1024 }
1015 1025
1016 // Static.
1017 bool SavePackage::GetBaseFileNameAndFileOrdinalNumber(
1018 const std::wstring& file_name,
1019 std::wstring* base_file_name,
1020 std::wstring* file_ordinal_number) {
1021 if (file_name.empty() || !base_file_name || !file_ordinal_number)
1022 return false;
1023
1024 // Find dot position.
1025 std::wstring::size_type dot_position = file_name.rfind(L".");
1026 // Find position of right parenthesis.
1027 std::wstring::size_type parenthesis_right;
1028 if (std::wstring::npos == dot_position)
1029 parenthesis_right = file_name.rfind(L')');
1030 else
1031 parenthesis_right = dot_position - 1;
1032 // The latest character of pure file name is not ")", return false.
1033 if (std::wstring::npos == parenthesis_right)
1034 return false;
1035 if (file_name.at(parenthesis_right) != L')')
1036 return false;
1037 // Find position of left parenthesis.
1038 std::wstring::size_type parenthesis_left = file_name.rfind(L'(');
1039 if (std::wstring::npos == parenthesis_left)
1040 return false;
1041
1042 if (parenthesis_right <= parenthesis_left)
1043 return false;
1044 // Check whether content between left parenthesis and right parenthesis is
1045 // numeric or not.
1046 std::wstring ordinal_number(file_name, parenthesis_left + 1,
1047 parenthesis_right - parenthesis_left - 1);
1048 for (std::wstring::const_iterator cit = ordinal_number.begin();
1049 cit != ordinal_number.end(); ++cit)
1050 if (!IsAsciiDigit(*cit))
1051 return false;
1052
1053 *base_file_name = std::wstring(file_name, 0, parenthesis_left);
1054 *file_ordinal_number = ordinal_number;
1055 return true;
1056 }
1057
1058 // Static 1026 // Static
1059 bool SavePackage::IsSavableURL(const GURL& url) { 1027 bool SavePackage::IsSavableURL(const GURL& url) {
1060 return url.SchemeIs("http") || url.SchemeIs("https") || 1028 return url.SchemeIs("http") || url.SchemeIs("https") ||
1061 url.SchemeIs("file") || url.SchemeIs("ftp"); 1029 url.SchemeIs("file") || url.SchemeIs("ftp");
1062 } 1030 }
1063 1031
1064 // Static 1032 // Static
1065 bool SavePackage::IsSavableContents(const std::string& contents_mime_type) { 1033 bool SavePackage::IsSavableContents(const std::string& contents_mime_type) {
1066 // WebKit creates Document object when MIME type is application/xhtml+xml, 1034 // WebKit creates Document object when MIME type is application/xhtml+xml,
1067 // so we also support this MIME type. 1035 // so we also support this MIME type.
1068 return contents_mime_type == "text/html" || 1036 return contents_mime_type == "text/html" ||
1069 contents_mime_type == "text/xml" || 1037 contents_mime_type == "text/xml" ||
1070 contents_mime_type == "application/xhtml+xml" || 1038 contents_mime_type == "application/xhtml+xml" ||
1071 contents_mime_type == "text/plain" || 1039 contents_mime_type == "text/plain" ||
1072 contents_mime_type == "text/css" || 1040 contents_mime_type == "text/css" ||
1073 net::IsSupportedJavascriptMimeType(contents_mime_type.c_str()); 1041 net::IsSupportedJavascriptMimeType(contents_mime_type.c_str());
1074 } 1042 }
1075 1043
1076 // Static 1044 // Static
1077 bool SavePackage::CanSaveAsComplete(const std::string& contents_mime_type) { 1045 bool SavePackage::CanSaveAsComplete(const std::string& contents_mime_type) {
1078 return contents_mime_type == "text/html"; 1046 return contents_mime_type == "text/html";
1079 } 1047 }
1080 1048
1081 // Static 1049 // Static
1082 bool SavePackage::GetSafePureFileName(const std::wstring& dir_path, 1050 bool SavePackage::GetSafePureFileName(const FilePath& dir_path,
1083 const std::wstring& file_name_ext, 1051 const FilePath::StringType& file_name_ext,
1084 uint32 max_file_path_len, 1052 uint32 max_file_path_len,
1085 std::wstring* pure_file_name) { 1053 FilePath::StringType* pure_file_name) {
1086 DCHECK(!pure_file_name->empty()); 1054 DCHECK(!pure_file_name->empty());
1087 std::wstring final_name = dir_path; 1055 int available_length = static_cast<int>(
1088 file_util::AppendToPath(&final_name, *pure_file_name); 1056 max_file_path_len - dir_path.value().length() - file_name_ext.length());
1089 // Get total length of dir path, including ending "\". 1057 // Need an extra space for the separator.
1090 const std::wstring::size_type dir_path_length = 1058 if (!file_util::EndsWithSeparator(dir_path))
1091 final_name.length() - pure_file_name->length(); 1059 --available_length;
1092 // Get available length for putting dir path and pure file name.
1093 const std::wstring::size_type available_length =
1094 static_cast<std::wstring::size_type>(max_file_path_len) -
1095 file_name_ext.length();
1096 1060
1097 if (final_name.length() <= available_length) 1061 // Plenty of room.
1062 if (static_cast<int>(pure_file_name->length()) <= available_length)
1098 return true; 1063 return true;
1099 1064
1100 if (available_length > dir_path_length) { 1065 // Limited room. Truncate |pure_file_name| to fit.
1066 if (available_length > 0) {
1101 *pure_file_name = 1067 *pure_file_name =
1102 pure_file_name->substr(0, available_length - dir_path_length); 1068 pure_file_name->substr(0, available_length);
1103 return true; 1069 return true;
1104 } else {
1105 pure_file_name->clear();
1106 return false;
1107 } 1070 }
1071
1072 // Not enough room to even use a shortened |pure_file_name|.
1073 pure_file_name->clear();
1074 return false;
1108 } 1075 }
1076
OLDNEW
« no previous file with comments | « chrome/browser/download/save_package.h ('k') | chrome/browser/download/save_package_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698