| 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 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1227 // Give backend the lists which contain all resource links that have local | 1227 // Give backend the lists which contain all resource links that have local |
| 1228 // storage, after which, render process will serialize DOM for generating | 1228 // storage, after which, render process will serialize DOM for generating |
| 1229 // HTML data. | 1229 // HTML data. |
| 1230 DoSavingProcess(); | 1230 DoSavingProcess(); |
| 1231 } else { | 1231 } else { |
| 1232 // No savable frames and/or resources - treat it as user cancel. | 1232 // No savable frames and/or resources - treat it as user cancel. |
| 1233 Cancel(true); | 1233 Cancel(true); |
| 1234 } | 1234 } |
| 1235 } | 1235 } |
| 1236 | 1236 |
| 1237 // static |
| 1237 base::FilePath SavePackage::GetSuggestedNameForSaveAs( | 1238 base::FilePath SavePackage::GetSuggestedNameForSaveAs( |
| 1239 const base::string16& title, |
| 1240 const GURL& page_url, |
| 1238 bool can_save_as_complete, | 1241 bool can_save_as_complete, |
| 1239 const std::string& contents_mime_type) { | 1242 const std::string& contents_mime_type) { |
| 1240 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1243 base::FilePath name_with_proper_ext = base::FilePath::FromUTF16Unsafe(title); |
| 1241 base::FilePath name_with_proper_ext = base::FilePath::FromUTF16Unsafe(title_); | |
| 1242 | 1244 |
| 1243 // If the page's title matches its URL, use the URL. Try to use the last path | 1245 // If the page's title matches its URL, use the URL. Try to use the last path |
| 1244 // component or if there is none, the domain as the file name. | 1246 // component or if there is none, the domain as the file name. |
| 1245 // Normally we want to base the filename on the page title, or if it doesn't | 1247 // Normally we want to base the filename on the page title, or if it doesn't |
| 1246 // exist, on the URL. It's not easy to tell if the page has no title, because | 1248 // exist, on the URL. It's not easy to tell if the page has no title, because |
| 1247 // if the page has no title, WebContents::GetTitle() will return the page's | 1249 // if the page has no title, WebContents::GetTitle() will return the page's |
| 1248 // URL (adjusted for display purposes). Therefore, we convert the "title" | 1250 // URL (adjusted for display purposes). Therefore, we convert the "title" |
| 1249 // back to a URL, and if it matches the original page URL, we know the page | 1251 // back to a URL, and if it matches the original page URL, we know the page |
| 1250 // had no title (or had a title equal to its URL, which is fine to treat | 1252 // had no title (or had a title equal to its URL, which is fine to treat |
| 1251 // similarly). | 1253 // similarly). |
| 1252 if (title_ == url_formatter::FormatUrl(page_url_)) { | 1254 if (title == url_formatter::FormatUrl(page_url)) { |
| 1253 std::string url_path; | 1255 std::string url_path; |
| 1254 if (!page_url_.SchemeIs(url::kDataScheme)) { | 1256 if (!page_url.SchemeIs(url::kDataScheme)) { |
| 1255 std::vector<std::string> url_parts = base::SplitString( | 1257 std::vector<std::string> url_parts = base::SplitString( |
| 1256 page_url_.path(), "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | 1258 page_url.path(), "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 1257 if (!url_parts.empty()) { | 1259 if (!url_parts.empty()) { |
| 1258 for (int i = static_cast<int>(url_parts.size()) - 1; i >= 0; --i) { | 1260 for (int i = static_cast<int>(url_parts.size()) - 1; i >= 0; --i) { |
| 1259 url_path = url_parts[i]; | 1261 url_path = url_parts[i]; |
| 1260 if (!url_path.empty()) | 1262 if (!url_path.empty()) |
| 1261 break; | 1263 break; |
| 1262 } | 1264 } |
| 1263 } | 1265 } |
| 1264 if (url_path.empty()) | 1266 if (url_path.empty()) |
| 1265 url_path = page_url_.host(); | 1267 url_path = page_url.host(); |
| 1266 } else { | 1268 } else { |
| 1267 url_path = "dataurl"; | 1269 url_path = "dataurl"; |
| 1268 } | 1270 } |
| 1269 name_with_proper_ext = base::FilePath::FromUTF8Unsafe(url_path); | 1271 name_with_proper_ext = base::FilePath::FromUTF8Unsafe(url_path); |
| 1270 } | 1272 } |
| 1271 | 1273 |
| 1272 // Ask user for getting final saving name. | 1274 // Ask user for getting final saving name. |
| 1273 name_with_proper_ext = EnsureMimeExtension(name_with_proper_ext, | 1275 name_with_proper_ext = EnsureMimeExtension(name_with_proper_ext, |
| 1274 contents_mime_type); | 1276 contents_mime_type); |
| 1275 // Adjust extension for complete types. | 1277 // Adjust extension for complete types. |
| 1276 if (can_save_as_complete) | 1278 if (can_save_as_complete) |
| 1277 name_with_proper_ext = EnsureHtmlExtension(name_with_proper_ext); | 1279 name_with_proper_ext = EnsureHtmlExtension(name_with_proper_ext); |
| 1278 | 1280 |
| 1279 base::FilePath::StringType file_name = name_with_proper_ext.value(); | 1281 base::FilePath::StringType file_name = name_with_proper_ext.value(); |
| 1280 base::i18n::ReplaceIllegalCharactersInPath(&file_name, '_'); | 1282 base::i18n::ReplaceIllegalCharactersInPath(&file_name, '_'); |
| 1281 return base::FilePath(file_name); | 1283 return base::FilePath(file_name); |
| 1282 } | 1284 } |
| 1283 | 1285 |
| 1284 // static | 1286 // static |
| 1285 base::FilePath SavePackage::EnsureHtmlExtension(const base::FilePath& name) { | 1287 base::FilePath SavePackage::EnsureHtmlExtension(const base::FilePath& name) { |
| 1288 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 1289 |
| 1286 base::FilePath::StringType ext = name.Extension(); | 1290 base::FilePath::StringType ext = name.Extension(); |
| 1287 if (!ext.empty()) | 1291 if (!ext.empty()) |
| 1288 ext.erase(ext.begin()); // Erase preceding '.'. | 1292 ext.erase(ext.begin()); // Erase preceding '.'. |
| 1289 std::string mime_type; | 1293 std::string mime_type; |
| 1290 if (!net::GetMimeTypeFromExtension(ext, &mime_type) || | 1294 if (!net::GetMimeTypeFromExtension(ext, &mime_type) || |
| 1291 !CanSaveAsComplete(mime_type)) { | 1295 !CanSaveAsComplete(mime_type)) { |
| 1292 return base::FilePath(name.value() + FILE_PATH_LITERAL(".") + | 1296 return base::FilePath(name.value() + FILE_PATH_LITERAL(".") + |
| 1293 kDefaultHtmlExtension); | 1297 kDefaultHtmlExtension); |
| 1294 } | 1298 } |
| 1295 return name; | 1299 return name; |
| 1296 } | 1300 } |
| 1297 | 1301 |
| 1298 // static | 1302 // static |
| 1299 base::FilePath SavePackage::EnsureMimeExtension(const base::FilePath& name, | 1303 base::FilePath SavePackage::EnsureMimeExtension(const base::FilePath& name, |
| 1300 const std::string& contents_mime_type) { | 1304 const std::string& contents_mime_type) { |
| 1305 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 1306 |
| 1301 // Start extension at 1 to skip over period if non-empty. | 1307 // Start extension at 1 to skip over period if non-empty. |
| 1302 base::FilePath::StringType ext = name.Extension(); | 1308 base::FilePath::StringType ext = name.Extension(); |
| 1303 if (!ext.empty()) | 1309 if (!ext.empty()) |
| 1304 ext = ext.substr(1); | 1310 ext = ext.substr(1); |
| 1305 base::FilePath::StringType suggested_extension = | 1311 base::FilePath::StringType suggested_extension = |
| 1306 ExtensionForMimeType(contents_mime_type); | 1312 ExtensionForMimeType(contents_mime_type); |
| 1307 std::string mime_type; | 1313 std::string mime_type; |
| 1308 if (!suggested_extension.empty() && | 1314 if (!suggested_extension.empty() && |
| 1309 !net::GetMimeTypeFromExtension(ext, &mime_type)) { | 1315 !net::GetMimeTypeFromExtension(ext, &mime_type)) { |
| 1310 // Extension is absent or needs to be updated. | 1316 // Extension is absent or needs to be updated. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1342 base::FilePath download_save_dir; | 1348 base::FilePath download_save_dir; |
| 1343 bool skip_dir_check = false; | 1349 bool skip_dir_check = false; |
| 1344 auto* delegate = download_manager_->GetDelegate(); | 1350 auto* delegate = download_manager_->GetDelegate(); |
| 1345 if (delegate) { | 1351 if (delegate) { |
| 1346 delegate->GetSaveDir( | 1352 delegate->GetSaveDir( |
| 1347 web_contents()->GetBrowserContext(), &website_save_dir, | 1353 web_contents()->GetBrowserContext(), &website_save_dir, |
| 1348 &download_save_dir, &skip_dir_check); | 1354 &download_save_dir, &skip_dir_check); |
| 1349 } | 1355 } |
| 1350 std::string mime_type = web_contents()->GetContentsMimeType(); | 1356 std::string mime_type = web_contents()->GetContentsMimeType(); |
| 1351 bool can_save_as_complete = CanSaveAsComplete(mime_type); | 1357 bool can_save_as_complete = CanSaveAsComplete(mime_type); |
| 1352 base::FilePath suggested_filename = | |
| 1353 GetSuggestedNameForSaveAs(can_save_as_complete, mime_type); | |
| 1354 BrowserThread::PostTaskAndReplyWithResult( | 1358 BrowserThread::PostTaskAndReplyWithResult( |
| 1355 BrowserThread::FILE, FROM_HERE, | 1359 BrowserThread::FILE, FROM_HERE, |
| 1356 base::Bind(&SavePackage::CreateDirectoryOnFileThread, website_save_dir, | 1360 base::Bind(&SavePackage::CreateDirectoryOnFileThread, title_, page_url_, |
| 1357 download_save_dir, suggested_filename, skip_dir_check), | 1361 can_save_as_complete, mime_type, website_save_dir, |
| 1362 download_save_dir, skip_dir_check), |
| 1358 base::Bind(&SavePackage::ContinueGetSaveInfo, this, | 1363 base::Bind(&SavePackage::ContinueGetSaveInfo, this, |
| 1359 can_save_as_complete)); | 1364 can_save_as_complete)); |
| 1360 } | 1365 } |
| 1361 | 1366 |
| 1362 // static | 1367 // static |
| 1363 base::FilePath SavePackage::CreateDirectoryOnFileThread( | 1368 base::FilePath SavePackage::CreateDirectoryOnFileThread( |
| 1369 const base::string16& title, |
| 1370 const GURL& page_url, |
| 1371 bool can_save_as_complete, |
| 1372 const std::string& mime_type, |
| 1364 const base::FilePath& website_save_dir, | 1373 const base::FilePath& website_save_dir, |
| 1365 const base::FilePath& download_save_dir, | 1374 const base::FilePath& download_save_dir, |
| 1366 const base::FilePath& suggested_filename, | |
| 1367 bool skip_dir_check) { | 1375 bool skip_dir_check) { |
| 1368 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 1376 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 1369 | 1377 |
| 1378 base::FilePath suggested_filename = GetSuggestedNameForSaveAs( |
| 1379 title, page_url, can_save_as_complete, mime_type); |
| 1380 |
| 1370 base::FilePath save_dir; | 1381 base::FilePath save_dir; |
| 1371 // If the default html/websites save folder doesn't exist... | 1382 // If the default html/websites save folder doesn't exist... |
| 1372 // We skip the directory check for gdata directories on ChromeOS. | 1383 // We skip the directory check for gdata directories on ChromeOS. |
| 1373 if (!skip_dir_check && !base::DirectoryExists(website_save_dir)) { | 1384 if (!skip_dir_check && !base::DirectoryExists(website_save_dir)) { |
| 1374 // If the default download dir doesn't exist, create it. | 1385 // If the default download dir doesn't exist, create it. |
| 1375 if (!base::DirectoryExists(download_save_dir)) { | 1386 if (!base::DirectoryExists(download_save_dir)) { |
| 1376 bool res = base::CreateDirectory(download_save_dir); | 1387 bool res = base::CreateDirectory(download_save_dir); |
| 1377 DCHECK(res); | 1388 DCHECK(res); |
| 1378 } | 1389 } |
| 1379 save_dir = download_save_dir; | 1390 save_dir = download_save_dir; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1464 } | 1475 } |
| 1465 | 1476 |
| 1466 void SavePackage::FinalizeDownloadEntry() { | 1477 void SavePackage::FinalizeDownloadEntry() { |
| 1467 DCHECK(download_); | 1478 DCHECK(download_); |
| 1468 | 1479 |
| 1469 download_manager_->OnSavePackageSuccessfullyFinished(download_); | 1480 download_manager_->OnSavePackageSuccessfullyFinished(download_); |
| 1470 RemoveObservers(); | 1481 RemoveObservers(); |
| 1471 } | 1482 } |
| 1472 | 1483 |
| 1473 } // namespace content | 1484 } // namespace content |
| OLD | NEW |