summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/file_util.h7
-rw-r--r--base/file_util_posix.cc17
-rw-r--r--chrome/browser/web_applications/web_app_mac.mm33
-rw-r--r--chrome/browser/web_applications/web_app_mac_unittest.mm23
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());