summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/shell_integration.h1
-rw-r--r--chrome/browser/ui/web_applications/web_app_ui.cc4
-rw-r--r--chrome/browser/web_applications/web_app_mac.h4
-rw-r--r--chrome/browser/web_applications/web_app_mac.mm97
-rw-r--r--chrome/browser/web_applications/web_app_mac_unittest.mm30
-rw-r--r--chrome/common/mac/app_mode_common.h12
-rw-r--r--chrome/common/mac/app_mode_common.mm3
7 files changed, 106 insertions, 45 deletions
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index 1306027..f781b00 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -103,6 +103,7 @@ class ShellIntegration {
base::FilePath extension_path;
gfx::ImageFamily favicon;
base::FilePath profile_path;
+ std::string profile_name;
};
// Info about which locations to create app shortcuts in.
diff --git a/chrome/browser/ui/web_applications/web_app_ui.cc b/chrome/browser/ui/web_applications/web_app_ui.cc
index b807bc7..c185bfd 100644
--- a/chrome/browser/ui/web_applications/web_app_ui.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/file_util.h"
#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
#include "base/string16.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/image_loader.h"
@@ -20,6 +21,7 @@
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
+#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_registrar.h"
@@ -423,6 +425,8 @@ void UpdateShortcutInfoForApp(const extensions::Extension& app,
shortcut_info->description = UTF8ToUTF16(app.description());
shortcut_info->extension_path = app.path();
shortcut_info->profile_path = profile->GetPath();
+ shortcut_info->profile_name =
+ profile->GetPrefs()->GetString(prefs::kProfileName);
}
void UpdateShortcutInfoAndIconForApp(
diff --git a/chrome/browser/web_applications/web_app_mac.h b/chrome/browser/web_applications/web_app_mac.h
index 91d46d7..d20aa22 100644
--- a/chrome/browser/web_applications/web_app_mac.h
+++ b/chrome/browser/web_applications/web_app_mac.h
@@ -65,6 +65,10 @@ class WebAppShortcutCreator {
private:
FRIEND_TEST_ALL_PREFIXES(WebAppShortcutCreatorTest, UpdateIcon);
+ // Updates the InfoPlist.string inside |app_path| with the display name for
+ // the app.
+ bool UpdateDisplayName(const base::FilePath& app_path) const;
+
// Path to the app's user data directory. For example:
// ~/Library/Application Support/Chromium/Default/Web Applications/_crx_abc/
// Note, the user data directory is the parent of the profile directory.
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm
index a884e84..64caabd 100644
--- a/chrome/browser/web_applications/web_app_mac.mm
+++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -18,6 +18,7 @@
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
+#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/web_applications/web_app_ui.h"
#include "chrome/browser/web_applications/web_app.h"
@@ -132,6 +133,31 @@ base::FilePath GetWritableApplicationsDirectory() {
return base::FilePath();
}
+// Given the path to an app bundle, return the resources directory.
+base::FilePath GetResourcesPath(const base::FilePath& app_path) {
+ return app_path.Append("Contents").Append("Resources");
+}
+
+bool HasExistingExtensionShim(const base::FilePath& destination_directory,
+ const std::string& extension_id,
+ const base::FilePath& own_basename) {
+ // Check if there any any other shims for the same extension.
+ file_util::FileEnumerator enumerator(destination_directory,
+ false /* recursive */,
+ file_util::FileEnumerator::DIRECTORIES);
+ for (base::FilePath shim_path = enumerator.Next();
+ !shim_path.empty(); shim_path = enumerator.Next()) {
+ if (shim_path.BaseName() != own_basename &&
+ EndsWith(shim_path.RemoveExtension().value(),
+ extension_id,
+ true /* case_sensitive */)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
} // namespace
namespace web_app {
@@ -155,15 +181,16 @@ base::FilePath WebAppShortcutCreator::GetShortcutPath() const {
if (dst_path.empty())
return dst_path;
- base::FilePath app_name = internals::GetSanitizedFileName(info_.title);
+ base::FilePath app_name = internals::GetSanitizedFileName(UTF8ToUTF16(
+ info_.profile_path.BaseName().value() + " " + info_.extension_id));
return dst_path.Append(app_name.ReplaceExtension("app"));
}
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())) {
+ base::FilePath app_path = GetShortcutPath();
+ base::FilePath app_name = app_path.BaseName();
+ base::FilePath dst_path = app_path.DirName();
+ if (app_path.empty() || !file_util::DirectoryExists(dst_path.DirName())) {
LOG(ERROR) << "Couldn't find an Applications directory to copy app to.";
return false;
}
@@ -172,19 +199,10 @@ bool WebAppShortcutCreator::CreateShortcut() {
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;
- base::FilePath staging_path = scoped_temp_dir.path().Append(app_file_name);
+ base::FilePath staging_path = scoped_temp_dir.path().Append(app_name);
// Update the app's plist and icon in a temp directory. This works around
// a Finder bug where the app's icon doesn't properly update.
@@ -197,6 +215,9 @@ bool WebAppShortcutCreator::CreateShortcut() {
if (!UpdatePlist(staging_path))
return false;
+ if (!UpdateDisplayName(staging_path))
+ return false;
+
if (!UpdateIcon(staging_path))
return false;
@@ -224,9 +245,6 @@ base::FilePath WebAppShortcutCreator::GetDestinationPath() const {
}
bool WebAppShortcutCreator::UpdatePlist(const base::FilePath& app_path) const {
- NSString* plist_path = base::mac::FilePathToNSString(
- app_path.Append("Contents").Append("Info.plist"));
-
NSString* extension_id = base::SysUTF8ToNSString(info_.extension_id);
NSString* extension_title = base::SysUTF16ToNSString(info_.title);
NSString* extension_url = base::SysUTF8ToNSString(info_.url.spec());
@@ -239,6 +257,8 @@ bool WebAppShortcutCreator::UpdatePlist(const base::FilePath& app_path) const {
chrome_bundle_id, app_mode::kShortcutBrowserBundleIDPlaceholder,
nil];
+ NSString* plist_path = base::mac::FilePathToNSString(
+ app_path.Append("Contents").Append("Info.plist"));
NSMutableDictionary* plist =
[NSMutableDictionary dictionaryWithContentsOfFile:plist_path];
NSArray* keys = [plist allKeys];
@@ -265,9 +285,47 @@ bool WebAppShortcutCreator::UpdatePlist(const base::FilePath& app_path) const {
forKey:app_mode::kCrAppModeUserDataDirKey];
[plist setObject:base::mac::FilePathToNSString(info_.profile_path.BaseName())
forKey:app_mode::kCrAppModeProfileDirKey];
+ [plist setObject:base::SysUTF8ToNSString(info_.profile_name)
+ forKey:app_mode::kCrAppModeProfileNameKey];
+ [plist setObject:[NSNumber numberWithBool:YES]
+ forKey:app_mode::kLSHasLocalizedDisplayNameKey];
+
+ base::FilePath app_name = app_path.BaseName().RemoveExtension();
+ [plist setObject:base::mac::FilePathToNSString(app_name)
+ forKey:base::mac::CFToNSCast(kCFBundleNameKey)];
+
return [plist writeToFile:plist_path atomically:YES];
}
+bool WebAppShortcutCreator::UpdateDisplayName(
+ const base::FilePath& app_path) const {
+ // OSX searches for the best language in the order of preferred languages.
+ // Since we only have one localization directory, it will choose this one.
+ base::FilePath localized_dir = GetResourcesPath(app_path).Append("en.lproj");
+ if (!file_util::CreateDirectory(localized_dir))
+ return false;
+
+ NSString* bundle_name = base::SysUTF16ToNSString(info_.title);
+ NSString* display_name = base::SysUTF16ToNSString(info_.title);
+ if (HasExistingExtensionShim(GetDestinationPath(),
+ info_.extension_id,
+ app_path.BaseName())) {
+ display_name = [bundle_name
+ stringByAppendingString:base::SysUTF8ToNSString(
+ " (" + info_.profile_name + ")")];
+ }
+
+ NSDictionary* strings_plist = @{
+ base::mac::CFToNSCast(kCFBundleNameKey) : bundle_name,
+ app_mode::kCFBundleDisplayNameKey : display_name
+ };
+
+ NSString* localized_path = base::mac::FilePathToNSString(
+ localized_dir.Append("InfoPlist.strings"));
+ return [strings_plist writeToFile:localized_path
+ atomically:YES];
+}
+
bool WebAppShortcutCreator::UpdateIcon(const base::FilePath& app_path) const {
if (info_.favicon.empty())
return true;
@@ -290,8 +348,7 @@ bool WebAppShortcutCreator::UpdateIcon(const base::FilePath& app_path) const {
if (!image_added)
return false;
- base::FilePath resources_path =
- app_path.Append("Contents").Append("Resources");
+ base::FilePath resources_path = GetResourcesPath(app_path);
if (!file_util::CreateDirectory(resources_path))
return false;
diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm
index 0c08366..653bbb5 100644
--- a/chrome/browser/web_applications/web_app_mac_unittest.mm
+++ b/chrome/browser/web_applications/web_app_mac_unittest.mm
@@ -50,6 +50,7 @@ ShellIntegration::ShortcutInfo GetShortcutInfo() {
info.title = ASCIIToUTF16("Shortcut Title");
info.url = GURL("http://example.com/");
info.profile_path = base::FilePath("Default");
+ info.profile_name = "profile name";
return info;
}
@@ -64,7 +65,8 @@ TEST(WebAppShortcutCreatorTest, CreateShortcut) {
ShellIntegration::ShortcutInfo info = GetShortcutInfo();
base::FilePath dst_folder = scoped_temp_dir.path();
- base::FilePath dst_path = dst_folder.Append(UTF16ToUTF8(info.title) + ".app");
+ base::FilePath dst_path = dst_folder.Append(
+ info.profile_path.value() + " " + info.extension_id + ".app");
NiceMock<WebAppShortcutCreatorMock> shortcut_creator(info);
EXPECT_CALL(shortcut_creator, GetDestinationPath())
@@ -103,7 +105,8 @@ TEST(WebAppShortcutCreatorTest, RunShortcut) {
ShellIntegration::ShortcutInfo info = GetShortcutInfo();
base::FilePath dst_folder = scoped_temp_dir.path();
- base::FilePath dst_path = dst_folder.Append(UTF16ToUTF8(info.title) + ".app");
+ base::FilePath dst_path = dst_folder.Append(
+ info.profile_path.value() + " " + info.extension_id + ".app");
NiceMock<WebAppShortcutCreatorMock> shortcut_creator(info);
EXPECT_CALL(shortcut_creator, GetDestinationPath())
@@ -132,29 +135,6 @@ 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());
diff --git a/chrome/common/mac/app_mode_common.h b/chrome/common/mac/app_mode_common.h
index 8bb114f..b9045a6 100644
--- a/chrome/common/mac/app_mode_common.h
+++ b/chrome/common/mac/app_mode_common.h
@@ -33,6 +33,15 @@ extern const char kAppListModeId[];
// associates the shim without launching the app.
extern const char kNoLaunchApp[];
+// The display name of the bundle as shown in Finder and the Dock. For localized
+// bundles, this overrides the bundle's file name.
+extern NSString* const kCFBundleDisplayNameKey;
+
+// The key specifying whether the display name should be localized. This makes
+// Finder look in localization folders in the app bundle for a display name.
+// (e.g. Content/Resources/en.lproj/)
+extern NSString* const kLSHasLocalizedDisplayNameKey;
+
// The key under which the browser's bundle ID will be stored in the
// app mode launcher bundle's Info.plist.
extern NSString* const kBrowserBundleIDKey;
@@ -52,6 +61,9 @@ extern NSString* const kCrAppModeUserDataDirKey;
// Key for the app's extension path.
extern NSString* const kCrAppModeProfileDirKey;
+// Key for the app's profile display name.
+extern NSString* const kCrAppModeProfileNameKey;
+
// When the Chrome browser is run, it stores its location in the defaults
// system using this key.
extern NSString* const kLastRunAppBundlePathPrefsKey;
diff --git a/chrome/common/mac/app_mode_common.mm b/chrome/common/mac/app_mode_common.mm
index ae5e2f7..f67eb2f 100644
--- a/chrome/common/mac/app_mode_common.mm
+++ b/chrome/common/mac/app_mode_common.mm
@@ -12,12 +12,15 @@ const char kAppListModeId[] = "app_list";
const char kNoLaunchApp[] = "no-launch-app";
+NSString* const kCFBundleDisplayNameKey = @"CFBundleDisplayName";
+NSString* const kLSHasLocalizedDisplayNameKey = @"LSHasLocalizedDisplayName";
NSString* const kBrowserBundleIDKey = @"CrBundleIdentifier";
NSString* const kCrAppModeShortcutIDKey = @"CrAppModeShortcutID";
NSString* const kCrAppModeShortcutNameKey = @"CrAppModeShortcutName";
NSString* const kCrAppModeShortcutURLKey = @"CrAppModeShortcutURL";
NSString* const kCrAppModeUserDataDirKey = @"CrAppModeUserDataDir";
NSString* const kCrAppModeProfileDirKey = @"CrAppModeProfileDir";
+NSString* const kCrAppModeProfileNameKey = @"CrAppModeProfileName";
NSString* const kLastRunAppBundlePathPrefsKey = @"LastRunAppBundlePath";