diff options
-rw-r--r-- | base/file_util.h | 7 | ||||
-rw-r--r-- | base/file_util_posix.cc | 17 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac.mm | 33 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac_unittest.mm | 23 |
4 files changed, 68 insertions, 12 deletions
diff --git a/base/file_util.h b/base/file_util.h index 9ba5e41..00be5c9 100644 --- a/base/file_util.h +++ b/base/file_util.h @@ -374,6 +374,13 @@ BASE_EXPORT int GetUniquePathNumber(const base::FilePath& path, const base::FilePath::StringType& suffix); #if defined(OS_POSIX) +// Creates a directory with a guaranteed unique name based on |path|, returning +// the pathname if successful, or an empty path if there was an error creating +// the directory. Does not create parent directories. +BASE_EXPORT base::FilePath MakeUniqueDirectory(const base::FilePath& path); +#endif + +#if defined(OS_POSIX) // Test that |path| can only be changed by a given user and members of // a given set of groups. // Specifically, test that all parts of |path| under (and including) |base|: diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc index 1fbe520..fa2c1ff 100644 --- a/base/file_util_posix.cc +++ b/base/file_util_posix.cc @@ -538,6 +538,23 @@ bool CreateDirectory(const FilePath& full_path) { return true; } +base::FilePath MakeUniqueDirectory(const base::FilePath& path) { + const int kMaxAttempts = 20; + for (int attempts = 0; attempts < kMaxAttempts; attempts++) { + int uniquifier = GetUniquePathNumber(path, FILE_PATH_LITERAL("")); + if (uniquifier < 0) + break; + base::FilePath test_path = (uniquifier == 0) ? path : + path.InsertBeforeExtensionASCII( + base::StringPrintf(" (%d)", uniquifier)); + if (mkdir(test_path.value().c_str(), 0777) == 0) + return test_path; + else if (errno != EEXIST) + break; + } + return base::FilePath(); +} + // TODO(rkc): Refactor GetFileInfo and FileEnumerator to handle symlinks // correctly. http://code.google.com/p/chromium-os/issues/detail?id=15948 bool IsLink(const FilePath& file_path) { diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm index bdea057..45fa13d 100644 --- a/chrome/browser/web_applications/web_app_mac.mm +++ b/chrome/browser/web_applications/web_app_mac.mm @@ -113,6 +113,25 @@ WebAppShortcutCreator::~WebAppShortcutCreator() { bool WebAppShortcutCreator::CreateShortcut() { base::FilePath app_name = internals::GetSanitizedFileName(info_.title); base::FilePath app_file_name = app_name.ReplaceExtension("app"); + base::FilePath dst_path = GetDestinationPath(); + if (dst_path.empty() || !file_util::DirectoryExists(dst_path.DirName())) { + LOG(ERROR) << "Couldn't find an Applications directory to copy app to."; + return false; + } + if (!file_util::CreateDirectory(dst_path)) { + LOG(ERROR) << "Creating directory " << dst_path.value() << " failed."; + return false; + } + + base::FilePath app_path = dst_path.Append(app_file_name); + app_path = file_util::MakeUniqueDirectory(app_path); + if (app_path.empty()) { + LOG(ERROR) << "Couldn't create a unique directory for app path: " + << app_path.value(); + return false; + } + app_file_name = app_path.BaseName(); + base::ScopedTempDir scoped_temp_dir; if (!scoped_temp_dir.CreateUniqueTempDir()) return false; @@ -132,23 +151,13 @@ bool WebAppShortcutCreator::CreateShortcut() { if (!UpdateIcon(staging_path)) return false; - base::FilePath dst_path = GetDestinationPath(); - if (dst_path.empty() || !file_util::DirectoryExists(dst_path.DirName())) { - LOG(ERROR) << "Couldn't find an Applications directory to copy app to."; - return false; - } - if (!file_util::CreateDirectory(dst_path)) { - LOG(ERROR) << "Creating directory " << dst_path.value() << " failed."; - return false; - } if (!file_util::CopyDirectory(staging_path, dst_path, true)) { LOG(ERROR) << "Copying app to dst path: " << dst_path.value() << " failed"; return false; } - dst_path = dst_path.Append(app_file_name); - base::mac::RemoveQuarantineAttribute(dst_path); - RevealGeneratedBundleInFinder(dst_path); + base::mac::RemoveQuarantineAttribute(app_path); + RevealGeneratedBundleInFinder(app_path); return true; } diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm index 7dbbfdf..eae79e5 100644 --- a/chrome/browser/web_applications/web_app_mac_unittest.mm +++ b/chrome/browser/web_applications/web_app_mac_unittest.mm @@ -131,6 +131,29 @@ TEST(WebAppShortcutCreatorTest, CreateFailure) { EXPECT_FALSE(shortcut_creator.CreateShortcut()); } +TEST(WebAppShortcutCreatorTest, CreateUnique) { + base::ScopedTempDir scoped_temp_dir; + EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); + + ShellIntegration::ShortcutInfo info = GetShortcutInfo(); + + base::FilePath dst_folder = scoped_temp_dir.path(); + base::FilePath dst_path = dst_folder.Append(UTF16ToUTF8(info.title) + ".app"); + + file_util::CreateDirectory(dst_path); + base::FilePath expected_app_path = + dst_path.InsertBeforeExtensionASCII(" (1)"); + + NiceMock<WebAppShortcutCreatorMock> shortcut_creator(info); + EXPECT_CALL(shortcut_creator, GetDestinationPath()) + .WillRepeatedly(Return(dst_folder)); + EXPECT_CALL(shortcut_creator, + RevealGeneratedBundleInFinder(expected_app_path)); + + EXPECT_TRUE(shortcut_creator.CreateShortcut()); + EXPECT_TRUE(file_util::PathExists(expected_app_path)); +} + TEST(WebAppShortcutCreatorTest, UpdateIcon) { base::ScopedTempDir scoped_temp_dir; ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir()); |