| Index: chrome/browser/download/save_package.cc
|
| ===================================================================
|
| --- chrome/browser/download/save_package.cc (revision 9445)
|
| +++ chrome/browser/download/save_package.cc (working copy)
|
| @@ -43,6 +43,9 @@
|
|
|
| namespace {
|
|
|
| +const FilePath::CharType kLeftParen = FILE_PATH_LITERAL('(');
|
| +const FilePath::CharType kRightParen = FILE_PATH_LITERAL(')');
|
| +
|
| // Default name which will be used when we can not get proper name from
|
| // resource URL.
|
| const wchar_t kDefaultSaveName[] = L"saved_resource";
|
| @@ -65,12 +68,33 @@
|
| // exists only for testing.
|
| bool g_should_prompt_for_filename = true;
|
|
|
| +// Strip current ordinal number, if any. Should only be used on pure
|
| +// file names, i.e. those stripped of their extensions.
|
| +// TODO(estade): improve this to not choke on alternate encodings.
|
| +FilePath::StringType StripOrdinalNumber(
|
| + const FilePath::StringType& pure_file_name) {
|
| + FilePath::StringType::size_type r_paren_index =
|
| + pure_file_name.rfind(FILE_PATH_LITERAL(')'));
|
| + FilePath::StringType::size_type l_paren_index =
|
| + pure_file_name.rfind(FILE_PATH_LITERAL('('));
|
| + if (l_paren_index >= r_paren_index)
|
| + return pure_file_name;
|
| +
|
| + for (FilePath::StringType::size_type i = l_paren_index + 1;
|
| + i != r_paren_index; ++i) {
|
| + if (!IsAsciiDigit(pure_file_name[i]))
|
| + return pure_file_name;
|
| + }
|
| +
|
| + return pure_file_name.substr(0, l_paren_index);
|
| +}
|
| +
|
| } // namespace
|
|
|
| SavePackage::SavePackage(WebContents* web_content,
|
| SavePackageType save_type,
|
| - const std::wstring& file_full_path,
|
| - const std::wstring& directory_full_path)
|
| + const FilePath& file_full_path,
|
| + const FilePath& directory_full_path)
|
| : web_contents_(web_content),
|
| save_type_(save_type),
|
| saved_main_file_path_(file_full_path),
|
| @@ -89,15 +113,15 @@
|
| DCHECK(save_type_ == SAVE_AS_ONLY_HTML ||
|
| save_type_ == SAVE_AS_COMPLETE_HTML);
|
| DCHECK(!saved_main_file_path_.empty() &&
|
| - saved_main_file_path_.length() <= kMaxFilePathLength);
|
| + saved_main_file_path_.value().length() <= kMaxFilePathLength);
|
| DCHECK(!saved_main_directory_path_.empty() &&
|
| - saved_main_directory_path_.length() < kMaxFilePathLength);
|
| + saved_main_directory_path_.value().length() < kMaxFilePathLength);
|
| }
|
|
|
| // This is for testing use. Set |finished_| as true because we don't want
|
| // method Cancel to be be called in destructor in test mode.
|
| -SavePackage::SavePackage(const wchar_t* file_full_path,
|
| - const wchar_t* directory_full_path)
|
| +SavePackage::SavePackage(const FilePath::CharType* file_full_path,
|
| + const FilePath::CharType* directory_full_path)
|
| : all_save_items_count_(0),
|
| saved_main_file_path_(file_full_path),
|
| saved_main_directory_path_(directory_full_path),
|
| @@ -107,9 +131,9 @@
|
| disk_error_occurred_(false),
|
| tab_id_(0) {
|
| DCHECK(!saved_main_file_path_.empty() &&
|
| - saved_main_file_path_.length() <= kMaxFilePathLength);
|
| + saved_main_file_path_.value().length() <= kMaxFilePathLength);
|
| DCHECK(!saved_main_directory_path_.empty() &&
|
| - saved_main_directory_path_.length() < kMaxFilePathLength);
|
| + saved_main_directory_path_.value().length() < kMaxFilePathLength);
|
| }
|
|
|
| SavePackage::~SavePackage() {
|
| @@ -186,8 +210,7 @@
|
| }
|
|
|
| // Create the fake DownloadItem and display the view.
|
| - download_ = new DownloadItem(1,
|
| - FilePath::FromWStringHack(saved_main_file_path_), 0, page_url_,
|
| + download_ = new DownloadItem(1, saved_main_file_path_, 0, page_url_,
|
| FilePath(), Time::Now(), 0, -1, -1, false);
|
| download_->set_manager(web_contents_->profile()->GetDownloadManager());
|
| DownloadShelfView* shelf = web_contents_->GetDownloadShelfView();
|
| @@ -223,46 +246,35 @@
|
|
|
| // Generate name for saving resource.
|
| bool SavePackage::GenerateFilename(const std::string& disposition,
|
| - const std::wstring& url,
|
| + const GURL& url,
|
| bool need_html_ext,
|
| - std::wstring* generated_name) {
|
| - std::wstring file_name =
|
| - net::GetSuggestedFilename(GURL(url), disposition, kDefaultSaveName);
|
| + FilePath::StringType* generated_name) {
|
| + FilePath file_path = FilePath::FromWStringHack(
|
| + net::GetSuggestedFilename(url, disposition, kDefaultSaveName));
|
|
|
| - DCHECK(!file_name.empty());
|
| - // Check whether we have same name before.
|
| - std::wstring::size_type last_dot = file_name.rfind(L'.');
|
| - std::wstring pure_file_name, file_name_ext;
|
| - if (last_dot == std::wstring::npos) {
|
| - pure_file_name = file_name;
|
| - } else {
|
| - pure_file_name = std::wstring(file_name, 0, last_dot);
|
| - file_name_ext = std::wstring(file_name, last_dot);
|
| - }
|
| + DCHECK(!file_path.empty());
|
| + FilePath::StringType pure_file_name =
|
| + file_path.RemoveExtension().BaseName().value();
|
| + FilePath::StringType file_name_ext = file_path.Extension();
|
| +
|
| // If it is HTML resource, use ".htm" as its extension name.
|
| if (need_html_ext)
|
| - file_name_ext = L".htm";
|
| - if (file_name_ext == L".")
|
| - file_name_ext.clear();
|
| + file_name_ext = FILE_PATH_LITERAL(".htm");
|
|
|
| // Get safe pure file name.
|
| if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
|
| kMaxFilePathLength, &pure_file_name))
|
| return false;
|
|
|
| - file_name = pure_file_name + file_name_ext;
|
| + FilePath::StringType file_name = pure_file_name + file_name_ext;
|
|
|
| // Check whether we already have same name.
|
| if (file_name_set_.find(file_name) == file_name_set_.end()) {
|
| file_name_set_.insert(file_name);
|
| } else {
|
| // Found same name, increase the ordinal number for the file name.
|
| - std::wstring base_file_name, file_ordinal_number;
|
| + FilePath::StringType base_file_name = StripOrdinalNumber(pure_file_name);
|
|
|
| - if (!GetBaseFileNameAndFileOrdinalNumber(pure_file_name, &base_file_name,
|
| - &file_ordinal_number))
|
| - base_file_name = pure_file_name;
|
| -
|
| // We need to make sure the length of base file name plus maximum ordinal
|
| // number path will be less than or equal to kMaxFilePathLength.
|
| if (!GetSafePureFileName(saved_main_directory_path_, file_name_ext,
|
| @@ -283,17 +295,19 @@
|
|
|
| if (ordinal_number > (kMaxFileOrdinalNumber - 1)) {
|
| // Use a random file from temporary file.
|
| - file_util::CreateTemporaryFileName(&file_name);
|
| - file_name = file_util::GetFilenameFromPath(file_name);
|
| + FilePath temp_file;
|
| + file_util::CreateTemporaryFileName(&temp_file);
|
| + file_name = temp_file.RemoveExtension().BaseName().value();
|
| // Get safe pure file name.
|
| - if (!GetSafePureFileName(saved_main_directory_path_, std::wstring(),
|
| + if (!GetSafePureFileName(saved_main_directory_path_,
|
| + FilePath::StringType(),
|
| kMaxFilePathLength, &file_name))
|
| return false;
|
| } else {
|
| uint32 i;
|
| for (i = ordinal_number; i < kMaxFileOrdinalNumber; ++i) {
|
| - std::wstring new_name =
|
| - StringPrintf(L"%ls(%d)", base_file_name.c_str(), i) + file_name_ext;
|
| + FilePath::StringType new_name = base_file_name +
|
| + StringPrintf(FILE_PATH_LITERAL("(%d)"), i) + file_name_ext;
|
| if (file_name_set_.find(new_name) == file_name_set_.end()) {
|
| // Resolved name conflict.
|
| file_name = new_name;
|
| @@ -334,7 +348,7 @@
|
| // save directory, or prompting the user.
|
| DCHECK(!save_item->has_final_name());
|
| if (info->url != page_url_) {
|
| - std::wstring generated_name;
|
| + FilePath::StringType generated_name;
|
| // For HTML resource file, make sure it will have .htm as extension name,
|
| // otherwise, when you open the saved page in Chrome again, download
|
| // file manager will treat it as downloadable resource, and download it
|
| @@ -342,7 +356,7 @@
|
| bool need_html_ext =
|
| info->save_source == SaveFileCreateInfo::SAVE_FILE_FROM_DOM;
|
| if (!GenerateFilename(info->content_disposition,
|
| - info->url,
|
| + GURL(info->url),
|
| need_html_ext,
|
| &generated_name)) {
|
| // We can not generate file name for this SaveItem, so we cancel the
|
| @@ -365,12 +379,11 @@
|
|
|
| // Now we get final name retrieved from GenerateFilename, we will use it
|
| // rename the SaveItem.
|
| - std::wstring final_name = saved_main_directory_path_;
|
| - file_util::AppendToPath(&final_name, generated_name);
|
| - save_item->Rename(final_name);
|
| + FilePath final_name = saved_main_directory_path_.Append(generated_name);
|
| + save_item->Rename(final_name.ToWStringHack());
|
| } else {
|
| // It is the main HTML file, use the name chosen by the user.
|
| - save_item->Rename(saved_main_file_path_);
|
| + save_item->Rename(saved_main_file_path_.ToWStringHack());
|
| }
|
|
|
| // If the save source is from file system, inform SaveFileManager to copy
|
| @@ -494,9 +507,9 @@
|
| if (in_process_count() || finished_)
|
| return;
|
|
|
| - std::wstring dir = save_type_ == SAVE_AS_COMPLETE_HTML ?
|
| - saved_main_directory_path_ :
|
| - L"";
|
| + FilePath dir = save_type_ == SAVE_AS_COMPLETE_HTML ?
|
| + saved_main_directory_path_ :
|
| + FilePath();
|
|
|
| // This vector contains the final names of all the successfully saved files
|
| // along with their save ids. It will be passed to SaveFileManager to do the
|
| @@ -511,7 +524,7 @@
|
| NewRunnableMethod(file_manager_,
|
| &SaveFileManager::RenameAllFiles,
|
| final_names,
|
| - dir,
|
| + dir.ToWStringHack(),
|
| web_contents_->process()->host_id(),
|
| web_contents_->render_view_host()->routing_id()));
|
| }
|
| @@ -671,7 +684,7 @@
|
| file_manager_->GetSaveLoop()->PostTask(FROM_HERE,
|
| NewRunnableMethod(file_manager_,
|
| &SaveFileManager::OnShowSavedFileInShell,
|
| - saved_main_file_path_));
|
| + saved_main_file_path_.ToWStringHack()));
|
| }
|
|
|
| // Calculate the percentage of whole save page job.
|
| @@ -763,16 +776,14 @@
|
| }
|
|
|
| // Get the relative directory name.
|
| - std::wstring::size_type last_slash = saved_main_directory_path_.rfind(L'\\');
|
| - DCHECK(last_slash != std::wstring::npos);
|
| - std::wstring relative_dir_name = std::wstring(saved_main_directory_path_,
|
| - last_slash + 1);
|
| + FilePath relative_dir_name = saved_main_directory_path_.BaseName();
|
|
|
| - relative_dir_name = std::wstring(L"./") + relative_dir_name + L"/";
|
| + std::wstring relative_dir_name_str = std::wstring(L"./") +
|
| + relative_dir_name.ToWStringHack() + L"/";
|
|
|
| web_contents_->render_view_host()->
|
| GetSerializedHtmlDataForCurrentPageWithLocalLinks(
|
| - saved_links, saved_file_paths, relative_dir_name);
|
| + saved_links, saved_file_paths, relative_dir_name_str);
|
| }
|
|
|
| // Process the serialized HTML content data of a specified web page
|
| @@ -899,17 +910,18 @@
|
| g_should_prompt_for_filename = should_prompt;
|
| }
|
|
|
| -std::wstring SavePackage::GetSuggestNameForSaveAs(PrefService* prefs,
|
| - const std::wstring& name) {
|
| +// static
|
| +FilePath SavePackage::GetSuggestNameForSaveAs(PrefService* prefs,
|
| + const FilePath& name) {
|
| // Check whether the preference has the preferred directory for saving file.
|
| // If not, initialize it with default directory.
|
| if (!prefs->IsPrefRegistered(prefs::kSaveFileDefaultDirectory)) {
|
| - std::wstring default_save_path;
|
| + FilePath default_save_path;
|
| if (!PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS,
|
| &default_save_path))
|
| NOTREACHED();
|
| prefs->RegisterStringPref(prefs::kSaveFileDefaultDirectory,
|
| - default_save_path);
|
| + default_save_path.ToWStringHack());
|
| }
|
|
|
| // Get the directory from preference.
|
| @@ -918,18 +930,16 @@
|
| DCHECK(!(*save_file_path).empty());
|
|
|
| // Ask user for getting final saving name.
|
| - std::wstring suggest_name, file_name;
|
| -
|
| - file_name = name;
|
| + std::wstring file_name = name.ToWStringHack();
|
| file_util::ReplaceIllegalCharacters(&file_name, L' ');
|
| - suggest_name = *save_file_path;
|
| - file_util::AppendToPath(&suggest_name, file_name);
|
| + FilePath suggest_name = FilePath::FromWStringHack(save_file_path.GetValue());
|
| + suggest_name = suggest_name.Append(file_name);
|
|
|
| return suggest_name;
|
| }
|
|
|
| // Static.
|
| -bool SavePackage::GetSaveInfo(const std::wstring& suggest_name,
|
| +bool SavePackage::GetSaveInfo(const FilePath& suggest_name,
|
| HWND container_hwnd,
|
| SavePackageParam* param,
|
| DownloadManager* download_manager) {
|
| @@ -952,21 +962,29 @@
|
| // Since we take the suggested name from the web page's title, we want to
|
| // ignore the file extension generated by SaveFileAsWithFilter, since it
|
| // will always be ".htm".
|
| + // TODO(estade): is this saved_main_file_path assignment behavior desired?
|
| + // It was copied from previous code but seems strange.
|
| + std::wstring main_file_path;
|
| if (!win_util::SaveFileAsWithFilter(container_hwnd,
|
| - suggest_name,
|
| + suggest_name.value(),
|
| filter,
|
| L"htm",
|
| true,
|
| &index,
|
| - ¶m->saved_main_file_path))
|
| + &main_file_path)) {
|
| + param->saved_main_file_path = FilePath(main_file_path);
|
| return false;
|
| + }
|
| } else {
|
| param->saved_main_file_path = suggest_name;
|
| }
|
| } else {
|
| if (g_should_prompt_for_filename) {
|
| - if (!win_util::SaveFileAs(container_hwnd, suggest_name,
|
| - ¶m->saved_main_file_path))
|
| + // TODO(estade): see above comment.
|
| + std::wstring main_file_path;
|
| + if (!win_util::SaveFileAs(container_hwnd, suggest_name.value(),
|
| + &main_file_path))
|
| + param->saved_main_file_path = FilePath(main_file_path);
|
| return false;
|
| } else {
|
| param->saved_main_file_path = suggest_name;
|
| @@ -978,83 +996,33 @@
|
|
|
| DCHECK(download_manager);
|
| // Ensure the filename is safe.
|
| - FilePath path(param->saved_main_file_path);
|
| - download_manager->GenerateSafeFilename(param->current_tab_mime_type, &path);
|
| - param->saved_main_file_path = path.ToWStringHack();
|
| + download_manager->GenerateSafeFilename(param->current_tab_mime_type,
|
| + ¶m->saved_main_file_path);
|
|
|
| // The option index is not zero-based.
|
| DCHECK(index > 0 && index < 3);
|
| - param->dir = file_util::GetDirectoryFromPath(param->saved_main_file_path);
|
| + param->dir = param->saved_main_file_path.DirName();
|
|
|
| StringPrefMember save_file_path;
|
| save_file_path.Init(prefs::kSaveFileDefaultDirectory, param->prefs, NULL);
|
| // If user change the default saving directory, we will remember it just
|
| // like IE and FireFox.
|
| - if (save_file_path.GetValue() != param->dir)
|
| - save_file_path.SetValue(param->dir);
|
| + if (save_file_path.GetValue() != param->dir.ToWStringHack())
|
| + save_file_path.SetValue(param->dir.ToWStringHack());
|
|
|
| param->save_type = (index == 1) ? SavePackage::SAVE_AS_ONLY_HTML :
|
| SavePackage::SAVE_AS_COMPLETE_HTML;
|
|
|
| if (param->save_type == SavePackage::SAVE_AS_COMPLETE_HTML) {
|
| // Make new directory for saving complete file.
|
| - std::wstring file_name =
|
| - file_util::GetFilenameFromPath(param->saved_main_file_path);
|
| - std::wstring::size_type last_dot = file_name.rfind(L'.');
|
| - std::wstring pure_file_name;
|
| - if (last_dot == std::wstring::npos)
|
| - pure_file_name = file_name;
|
| - else
|
| - pure_file_name = std::wstring(file_name, 0, last_dot);
|
| - pure_file_name += L"_files";
|
| - file_util::AppendToPath(¶m->dir, pure_file_name);
|
| + param->dir = param->dir.Append(
|
| + param->saved_main_file_path.RemoveExtension().BaseName().value() +
|
| + FILE_PATH_LITERAL("_files"));
|
| }
|
|
|
| return true;
|
| }
|
|
|
| -// Static.
|
| -bool SavePackage::GetBaseFileNameAndFileOrdinalNumber(
|
| - const std::wstring& file_name,
|
| - std::wstring* base_file_name,
|
| - std::wstring* file_ordinal_number) {
|
| - if (file_name.empty() || !base_file_name || !file_ordinal_number)
|
| - return false;
|
| -
|
| - // Find dot position.
|
| - std::wstring::size_type dot_position = file_name.rfind(L".");
|
| - // Find position of right parenthesis.
|
| - std::wstring::size_type parenthesis_right;
|
| - if (std::wstring::npos == dot_position)
|
| - parenthesis_right = file_name.rfind(L')');
|
| - else
|
| - parenthesis_right = dot_position - 1;
|
| - // The latest character of pure file name is not ")", return false.
|
| - if (std::wstring::npos == parenthesis_right)
|
| - return false;
|
| - if (file_name.at(parenthesis_right) != L')')
|
| - return false;
|
| - // Find position of left parenthesis.
|
| - std::wstring::size_type parenthesis_left = file_name.rfind(L'(');
|
| - if (std::wstring::npos == parenthesis_left)
|
| - return false;
|
| -
|
| - if (parenthesis_right <= parenthesis_left)
|
| - return false;
|
| - // Check whether content between left parenthesis and right parenthesis is
|
| - // numeric or not.
|
| - std::wstring ordinal_number(file_name, parenthesis_left + 1,
|
| - parenthesis_right - parenthesis_left - 1);
|
| - for (std::wstring::const_iterator cit = ordinal_number.begin();
|
| - cit != ordinal_number.end(); ++cit)
|
| - if (!IsAsciiDigit(*cit))
|
| - return false;
|
| -
|
| - *base_file_name = std::wstring(file_name, 0, parenthesis_left);
|
| - *file_ordinal_number = ordinal_number;
|
| - return true;
|
| -}
|
| -
|
| // Static
|
| bool SavePackage::IsSavableURL(const GURL& url) {
|
| return url.SchemeIs("http") || url.SchemeIs("https") ||
|
| @@ -1079,30 +1047,30 @@
|
| }
|
|
|
| // Static
|
| -bool SavePackage::GetSafePureFileName(const std::wstring& dir_path,
|
| - const std::wstring& file_name_ext,
|
| +bool SavePackage::GetSafePureFileName(const FilePath& dir_path,
|
| + const FilePath::StringType& file_name_ext,
|
| uint32 max_file_path_len,
|
| - std::wstring* pure_file_name) {
|
| + FilePath::StringType* pure_file_name) {
|
| DCHECK(!pure_file_name->empty());
|
| - std::wstring final_name = dir_path;
|
| - file_util::AppendToPath(&final_name, *pure_file_name);
|
| - // Get total length of dir path, including ending "\".
|
| - const std::wstring::size_type dir_path_length =
|
| - final_name.length() - pure_file_name->length();
|
| - // Get available length for putting dir path and pure file name.
|
| - const std::wstring::size_type available_length =
|
| - static_cast<std::wstring::size_type>(max_file_path_len) -
|
| - file_name_ext.length();
|
| + int available_length = static_cast<int>(
|
| + max_file_path_len - dir_path.value().length() - file_name_ext.length());
|
| + // Need an extra space for the separator.
|
| + if (!file_util::EndsWithSeparator(dir_path))
|
| + --available_length;
|
|
|
| - if (final_name.length() <= available_length)
|
| + // Plenty of room.
|
| + if (static_cast<int>(pure_file_name->length()) <= available_length)
|
| return true;
|
|
|
| - if (available_length > dir_path_length) {
|
| + // Limited room. Truncate |pure_file_name| to fit.
|
| + if (available_length > 0) {
|
| *pure_file_name =
|
| - pure_file_name->substr(0, available_length - dir_path_length);
|
| + pure_file_name->substr(0, available_length);
|
| return true;
|
| - } else {
|
| - pure_file_name->clear();
|
| - return false;
|
| }
|
| +
|
| + // Not enough room to even use a shortened |pure_file_name|.
|
| + pure_file_name->clear();
|
| + return false;
|
| }
|
| +
|
|
|