Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4146)

Unified Diff: chrome/browser/web_applications/web_app_mac.mm

Issue 15724019: Recreate shortcuts on app update. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Include profile dir in bundle id. Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/web_applications/web_app_mac.mm
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm
index 825e90814b525e65435f160cdcebf37a96668628..db4d3cea14e263dcc3dcb9a7484b86377e437468 100644
--- a/chrome/browser/web_applications/web_app_mac.mm
+++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -159,6 +159,16 @@ bool HasExistingExtensionShim(const base::FilePath& destination_directory,
return false;
}
+void DeleteShortcut(base::FilePath app_path) {
tapted 2013/06/18 06:54:59 const reference
tapted 2013/06/18 06:54:59 Maybe a more descriptive name, to distinguish it f
jackhou1 2013/06/18 08:32:40 Done.
jackhou1 2013/06/18 08:32:40 Done.
+ if (app_path.empty())
+ return;
+
+ file_util::Delete(app_path, true);
+ base::FilePath apps_folder = app_path.DirName();
+ if (file_util::IsDirectoryEmpty(apps_folder))
+ file_util::Delete(apps_folder, false);
+}
+
} // namespace
namespace web_app {
@@ -168,7 +178,7 @@ const char kChromeAppDirName[] = "Chrome Apps.localized";
WebAppShortcutCreator::WebAppShortcutCreator(
const base::FilePath& user_data_dir,
const ShellIntegration::ShortcutInfo& shortcut_info,
- const string16& chrome_bundle_id)
+ const std::string& chrome_bundle_id)
: user_data_dir_(user_data_dir),
info_(shortcut_info),
chrome_bundle_id_(chrome_bundle_id) {
@@ -177,34 +187,14 @@ WebAppShortcutCreator::WebAppShortcutCreator(
WebAppShortcutCreator::~WebAppShortcutCreator() {
}
-base::FilePath WebAppShortcutCreator::GetShortcutPath() const {
- base::FilePath dst_path = GetDestinationPath();
- if (dst_path.empty())
- return dst_path;
-
+base::FilePath WebAppShortcutCreator::GetShortcutName() const {
base::FilePath app_name = internals::GetSanitizedFileName(UTF8ToUTF16(
info_.profile_path.BaseName().value() + " " + info_.extension_id));
- return dst_path.Append(app_name.ReplaceExtension("app"));
+ return app_name.ReplaceExtension("app");
}
-bool WebAppShortcutCreator::CreateShortcut() {
- 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;
- }
- if (!file_util::CreateDirectory(dst_path)) {
- LOG(ERROR) << "Creating directory " << dst_path.value() << " failed.";
- return false;
- }
-
- base::ScopedTempDir scoped_temp_dir;
- if (!scoped_temp_dir.CreateUniqueTempDir())
- return false;
- base::FilePath staging_path = scoped_temp_dir.path().Append(app_name);
-
+bool WebAppShortcutCreator::BuildShortcut(
+ const base::FilePath& staging_path) const {
// 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.
if (!file_util::CopyDirectory(GetAppLoaderPath(), staging_path, true)) {
@@ -222,17 +212,83 @@ bool WebAppShortcutCreator::CreateShortcut() {
if (!UpdateIcon(staging_path))
return false;
- if (!file_util::CopyDirectory(staging_path, dst_path, true)) {
- LOG(ERROR) << "Copying app to dst path: " << dst_path.value() << " failed";
+ return true;
+}
+
+bool WebAppShortcutCreator::CreateShortcutsIn(
+ const std::vector<base::FilePath>& folders) const {
+ base::ScopedTempDir scoped_temp_dir;
+ if (!scoped_temp_dir.CreateUniqueTempDir())
+ return false;
+
+ base::FilePath app_name = GetShortcutName();
+ base::FilePath staging_path =
+ scoped_temp_dir.path().Append(app_name);
+ if (!BuildShortcut(staging_path))
return false;
+
+ for (std::vector<base::FilePath>::const_iterator it = folders.begin();
+ it != folders.end(); ++it) {
+ const base::FilePath& dst_path = *it;
+ if (!file_util::CopyDirectory(staging_path, dst_path, true)) {
+ LOG(ERROR) << "Copying app to dst path: " << dst_path.value()
+ << " failed";
+ return false;
+ }
+
+ base::mac::RemoveQuarantineAttribute(dst_path.Append(app_name));
}
- base::mac::RemoveQuarantineAttribute(app_path);
- RevealGeneratedBundleInFinder(app_path);
+ return true;
+}
+bool WebAppShortcutCreator::CreateShortcut() {
+ 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;
+ }
tapted 2013/06/18 06:54:59 nit: blank line after for early return
jackhou1 2013/06/18 08:32:40 Done.
+ if (!file_util::CreateDirectory(dst_path)) {
+ LOG(ERROR) << "Creating directory " << dst_path.value() << " failed.";
+ return false;
+ }
+
+ std::vector<base::FilePath> paths;
+ paths.push_back(dst_path);
+ if (!CreateShortcutsIn(paths))
+ return false;
+
+ RevealAppShimInFinder();
return true;
}
+void WebAppShortcutCreator::DeleteShortcuts() {
+ base::FilePath dst_path = GetDestinationPath();
+ if (!dst_path.empty())
+ DeleteShortcut(dst_path.Append(GetShortcutName()));
+ // In case the user has moved/renamed/copied the app bundle.
+ DeleteShortcut(GetAppBundleById(GetBundleIdentifier()));
+}
+
+bool WebAppShortcutCreator::UpdateShortcuts() {
+ base::FilePath dst_path = GetDestinationPath();
+ base::FilePath app_path = dst_path.Append(GetShortcutName());
+
+ // If the path does not exist, check if a matching bundle can be found
+ // elsewhere.
+ if (dst_path.empty() || !file_util::PathExists(app_path))
+ app_path = GetAppBundleById(GetBundleIdentifier());
+
+ if (app_path.empty())
+ return false;
+
+ file_util::Delete(app_path, true);
+
+ std::vector<base::FilePath> paths;
+ paths.push_back(app_path.DirName());
+ return CreateShortcutsIn(paths);
+}
+
base::FilePath WebAppShortcutCreator::GetAppLoaderPath() const {
return base::mac::PathForFrameworkBundleResource(
base::mac::NSToCFCast(@"app_mode_loader.app"));
@@ -249,7 +305,7 @@ bool WebAppShortcutCreator::UpdatePlist(const base::FilePath& app_path) const {
NSString* extension_id = base::SysUTF8ToNSString(info_.extension_id);
NSString* extension_title = base::SysUTF16ToNSString(info_.title);
NSString* extension_url = base::SysUTF8ToNSString(info_.url.spec());
- NSString* chrome_bundle_id = base::SysUTF16ToNSString(chrome_bundle_id_);
+ NSString* chrome_bundle_id = base::SysUTF8ToNSString(chrome_bundle_id_);
NSDictionary* replacement_dict =
[NSDictionary dictionaryWithObjectsAndKeys:
extension_id, app_mode::kShortcutIdPlaceholder,
@@ -280,7 +336,7 @@ bool WebAppShortcutCreator::UpdatePlist(const base::FilePath& app_path) const {
}
// 2. Fill in other values.
- [plist setObject:GetBundleIdentifier(plist)
+ [plist setObject:base::SysUTF8ToNSString(GetBundleIdentifier())
forKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)];
[plist setObject:base::mac::FilePathToNSString(user_data_dir_)
forKey:app_mode::kCrAppModeUserDataDirKey];
@@ -356,25 +412,44 @@ bool WebAppShortcutCreator::UpdateIcon(const base::FilePath& app_path) const {
return icon_family.WriteDataToFile(resources_path.Append("app.icns"));
}
-NSString* WebAppShortcutCreator::GetBundleIdentifier(NSDictionary* plist) const
-{
- NSString* bundle_id_template =
- base::mac::ObjCCast<NSString>(
- [plist objectForKey:base::mac::CFToNSCast(kCFBundleIdentifierKey)]);
- NSString* extension_id = base::SysUTF8ToNSString(info_.extension_id);
- NSString* placeholder =
- [NSString stringWithFormat:@"@%@@", app_mode::kShortcutIdPlaceholder];
- NSString* bundle_id =
- [bundle_id_template
- stringByReplacingOccurrencesOfString:placeholder
- withString:extension_id];
+base::FilePath WebAppShortcutCreator::GetAppBundleById(
+ const std::string& bundle_id) const {
+ base::mac::ScopedCFTypeRef<CFStringRef> bundle_id_cf(
+ base::SysUTF8ToCFStringRef(bundle_id));
+ CFURLRef url_ref = NULL;
+ OSStatus status = LSFindApplicationForInfo(
+ kLSUnknownCreator, bundle_id_cf.get(), NULL, NULL, &url_ref);
+ base::mac::ScopedCFTypeRef<CFURLRef> url(url_ref);
tapted 2013/06/18 06:54:59 move this below checking status != noErr?
jackhou1 2013/06/18 08:32:40 Done.
+
+ if (status != noErr)
+ return base::FilePath();
+
+ NSString* path_string = [base::mac::CFToNSCast(url.get()) path];
+ return base::FilePath([path_string fileSystemRepresentation]);
+}
+
+std::string WebAppShortcutCreator::GetBundleIdentifier() const {
+ // Replace spaces in the profile path with hyphen.
+ std::string normalized_profile_path;
+ ReplaceChars(info_.profile_path.BaseName().value(),
+ " ", "-", &normalized_profile_path);
+
+ // This matches APP_MODE_APP_BUNDLE_ID in chrome/chrome.gyp.
+ std::string bundle_id =
+ chrome_bundle_id_ + std::string(".app.") +
+ normalized_profile_path + "-" + info_.extension_id;
+
return bundle_id;
}
-void WebAppShortcutCreator::RevealGeneratedBundleInFinder(
- const base::FilePath& generated_bundle) const {
+void WebAppShortcutCreator::RevealAppShimInFinder() const {
+ base::FilePath dst_path = GetDestinationPath();
+ if (dst_path.empty())
+ return;
+
+ base::FilePath app_path = dst_path.Append(GetShortcutName());
[[NSWorkspace sharedWorkspace]
- selectFile:base::mac::FilePathToNSString(generated_bundle)
+ selectFile:base::mac::FilePathToNSString(app_path)
inFileViewerRootedAtPath:nil];
}
@@ -398,8 +473,10 @@ base::FilePath GetAppInstallPath(
const ShellIntegration::ShortcutInfo& shortcut_info) {
WebAppShortcutCreator shortcut_creator(base::FilePath(),
shortcut_info,
- string16());
- return shortcut_creator.GetShortcutPath();
+ std::string());
+ base::FilePath dst_path = shortcut_creator.GetDestinationPath();
+ return dst_path.empty() ?
+ base::FilePath() : dst_path.Append(shortcut_creator.GetShortcutName());
}
void MaybeLaunchShortcut(const ShellIntegration::ShortcutInfo& shortcut_info) {
@@ -413,51 +490,33 @@ void MaybeLaunchShortcut(const ShellIntegration::ShortcutInfo& shortcut_info) {
namespace internals {
-base::FilePath GetAppBundleByExtensionId(std::string extension_id) {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
- // This matches APP_MODE_APP_BUNDLE_ID in chrome/chrome.gyp.
- std::string bundle_id =
- base::mac::BaseBundleID() + std::string(".app.") + extension_id;
- base::mac::ScopedCFTypeRef<CFStringRef> bundle_id_cf(
- base::SysUTF8ToCFStringRef(bundle_id));
- CFURLRef url_ref = NULL;
- OSStatus status = LSFindApplicationForInfo(
- kLSUnknownCreator, bundle_id_cf.get(), NULL, NULL, &url_ref);
- base::mac::ScopedCFTypeRef<CFURLRef> url(url_ref);
-
- if (status != noErr)
- return base::FilePath();
-
- NSString* path_string = [base::mac::CFToNSCast(url.get()) path];
- return base::FilePath([path_string fileSystemRepresentation]);
-}
-
bool CreatePlatformShortcuts(
const base::FilePath& web_app_path,
const ShellIntegration::ShortcutInfo& shortcut_info,
- const ShellIntegration::ShortcutLocations& /*creation_locations*/) {
+ const ShellIntegration::ShortcutLocations& creation_locations) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
- string16 bundle_id = UTF8ToUTF16(base::mac::BaseBundleID());
- WebAppShortcutCreator shortcut_creator(web_app_path, shortcut_info,
- bundle_id);
+ WebAppShortcutCreator shortcut_creator(
+ web_app_path, shortcut_info, base::mac::BaseBundleID());
return shortcut_creator.CreateShortcut();
}
void DeletePlatformShortcuts(
const base::FilePath& web_app_path,
- const ShellIntegration::ShortcutInfo& info) {
+ const ShellIntegration::ShortcutInfo& shortcut_info) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
-
- base::FilePath bundle_path = GetAppBundleByExtensionId(info.extension_id);
- file_util::Delete(bundle_path, true);
+ WebAppShortcutCreator shortcut_creator(
+ web_app_path, shortcut_info, base::mac::BaseBundleID());
+ shortcut_creator.DeleteShortcuts();
}
void UpdatePlatformShortcuts(
const base::FilePath& web_app_path,
const string16& old_app_title,
const ShellIntegration::ShortcutInfo& shortcut_info) {
- // TODO(benwells): Implement this when shortcuts / weblings are enabled on
- // mac.
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ WebAppShortcutCreator shortcut_creator(
+ web_app_path, shortcut_info, base::mac::BaseBundleID());
+ shortcut_creator.UpdateShortcuts();
}
} // namespace internals

Powered by Google App Engine
This is Rietveld 408576698