summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/app_shortcut_manager.cc33
-rw-r--r--chrome/browser/shell_integration_linux.cc65
-rw-r--r--chrome/browser/shell_integration_linux.h18
-rw-r--r--chrome/browser/shell_integration_unittest.cc4
-rw-r--r--chrome/browser/web_applications/web_app.cc14
-rw-r--r--chrome/browser/web_applications/web_app.h11
-rw-r--r--chrome/browser/web_applications/web_app_linux.cc5
-rw-r--r--chrome/browser/web_applications/web_app_mac.mm6
-rw-r--r--chrome/browser/web_applications/web_app_win.cc5
9 files changed, 144 insertions, 17 deletions
diff --git a/chrome/browser/extensions/app_shortcut_manager.cc b/chrome/browser/extensions/app_shortcut_manager.cc
index 53aba19..a3357f8 100644
--- a/chrome/browser/extensions/app_shortcut_manager.cc
+++ b/chrome/browser/extensions/app_shortcut_manager.cc
@@ -36,6 +36,8 @@ AppShortcutManager::AppShortcutManager(Profile* profile)
tracker_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED,
content::Source<Profile>(profile_));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+ content::Source<Profile>(profile_));
}
void AppShortcutManager::OnImageLoaded(const gfx::Image& image,
@@ -61,15 +63,28 @@ void AppShortcutManager::OnImageLoaded(const gfx::Image& image,
void AppShortcutManager::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
- DCHECK(type == chrome::NOTIFICATION_EXTENSION_INSTALLED);
- #if !defined(OS_MACOSX)
- const Extension* extension = content::Details<const Extension>(
- details).ptr();
- if (!disable_shortcut_creation_for_tests &&
- extension->is_platform_app() &&
- extension->location() != Extension::LOAD)
- InstallApplicationShortcuts(extension);
- #endif
+#if !defined(OS_MACOSX)
+ switch (type) {
+ case chrome::NOTIFICATION_EXTENSION_INSTALLED: {
+ const Extension* extension = content::Details<const Extension>(
+ details).ptr();
+ if (!disable_shortcut_creation_for_tests &&
+ extension->is_platform_app() &&
+ extension->location() != Extension::LOAD) {
+ InstallApplicationShortcuts(extension);
+ }
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: {
+ std::string extension_id = *content::Details<std::string>(details).ptr();
+ if (!disable_shortcut_creation_for_tests)
+ web_app::DeleteAllShortcuts(profile_->GetPath(), extension_id);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+#endif
}
// static
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index 840f056..ea05095 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -154,6 +154,12 @@ bool CreateShortcutOnDesktop(const FilePath& shortcut_filename,
return true;
}
+void DeleteShortcutOnDesktop(const FilePath& shortcut_filename) {
+ FilePath desktop_path;
+ if (PathService::Get(chrome::DIR_USER_DESKTOP, &desktop_path))
+ file_util::Delete(desktop_path.Append(shortcut_filename), false);
+}
+
bool CreateShortcutInApplicationsMenu(const FilePath& shortcut_filename,
const std::string& contents) {
ScopedTempDir temp_dir;
@@ -183,6 +189,22 @@ bool CreateShortcutInApplicationsMenu(const FilePath& shortcut_filename,
return exit_code == 0;
}
+void DeleteShortcutInApplicationsMenu(const FilePath& shortcut_filename) {
+ std::vector<std::string> argv;
+ argv.push_back("xdg-desktop-menu");
+ argv.push_back("uninstall");
+
+ // Uninstall in user mode, to match the install.
+ argv.push_back("--mode");
+ argv.push_back("user");
+
+ // The file does not need to exist anywhere - xdg-desktop-menu will uninstall
+ // items from the menu with a matching name.
+ argv.push_back(shortcut_filename.value());
+ int exit_code;
+ LaunchXdgUtility(argv, &exit_code);
+}
+
// Quote a string such that it appears as one verbatim argument for the Exec
// key in a desktop file.
std::string QuoteArgForDesktopFileExec(const std::string& arg) {
@@ -455,7 +477,7 @@ bool GetDesktopShortcutTemplate(base::Environment* env,
return false;
}
-FilePath GetDesktopShortcutFilename(const GURL& url) {
+FilePath GetWebShortcutFilename(const GURL& url) {
// Use a prefix, because xdg-desktop-menu requires it.
std::string filename =
std::string(chrome::kBrowserProcessExecutableName) + "-" + url.spec();
@@ -479,6 +501,20 @@ FilePath GetDesktopShortcutFilename(const GURL& url) {
return FilePath();
}
+FilePath GetExtensionShortcutFilename(const FilePath& profile_path,
+ const std::string& extension_id) {
+ DCHECK(!extension_id.empty());
+
+ // Use a prefix, because xdg-desktop-menu requires it.
+ std::string filename(chrome::kBrowserProcessExecutableName);
+ filename.append("-")
+ .append(extension_id)
+ .append("-")
+ .append(profile_path.BaseName().value());
+ file_util::ReplaceIllegalCharactersInPath(&filename, '_');
+ return FilePath(filename.append(".desktop"));
+}
+
std::string GetDesktopFileContents(
const std::string& template_contents,
const std::string& app_name,
@@ -597,8 +633,19 @@ bool CreateDesktopShortcut(
const std::string& shortcut_template) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- FilePath shortcut_filename =
- ShellIntegrationLinux::GetDesktopShortcutFilename(shortcut_info.url);
+ FilePath shortcut_filename;
+ if (!shortcut_info.extension_id.empty()) {
+ shortcut_filename = GetExtensionShortcutFilename(
+ shortcut_info.profile_path, shortcut_info.extension_id);
+ // For extensions we do not want duplicate shortcuts. So, delete any that
+ // already exist and replace them.
+ if (shortcut_info.create_on_desktop)
+ DeleteShortcutOnDesktop(shortcut_filename);
+ if (shortcut_info.create_in_applications_menu)
+ DeleteShortcutInApplicationsMenu(shortcut_filename);
+ } else {
+ shortcut_filename = GetWebShortcutFilename(shortcut_info.url);
+ }
if (shortcut_filename.empty())
return false;
@@ -629,4 +676,16 @@ bool CreateDesktopShortcut(
return success;
}
+void DeleteDesktopShortcuts(const FilePath& profile_path,
+ const std::string& extension_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ FilePath shortcut_filename = GetExtensionShortcutFilename(
+ profile_path, extension_id);
+ DCHECK(!shortcut_filename.empty());
+
+ DeleteShortcutOnDesktop(shortcut_filename);
+ DeleteShortcutInApplicationsMenu(shortcut_filename);
+}
+
} // namespace ShellIntegrationLinux
diff --git a/chrome/browser/shell_integration_linux.h b/chrome/browser/shell_integration_linux.h
index 5886250..643068a 100644
--- a/chrome/browser/shell_integration_linux.h
+++ b/chrome/browser/shell_integration_linux.h
@@ -26,7 +26,12 @@ bool GetDesktopShortcutTemplate(base::Environment* env,
std::string* output);
// Returns filename for .desktop file based on |url|, sanitized for security.
-FilePath GetDesktopShortcutFilename(const GURL& url);
+FilePath GetWebShortcutFilename(const GURL& url);
+
+// Returns filename for .desktop file based on |profile_path| and
+// |extension_id|, sanitized for security.
+FilePath GetExtensionShortcutFilename(const FilePath& profile_path,
+ const std::string& extension_id);
// Returns contents for .desktop file based on |template_contents|, |url|
// and |title|. The |template_contents| should be contents of .desktop file
@@ -41,9 +46,20 @@ std::string GetDesktopFileContents(const std::string& template_contents,
const std::string& icon_name,
const FilePath& profile_path);
+
+// Create shortcuts on the desktop or in the application menu (as specified by
+// |shortcut_info|), for the web page or extension in |shortcut_info|. Use the
+// shortcut template contained in |shortcut_template|.
+// For extensions, duplicate shortcuts are avoided, so if a requested shortcut
+// already exists it is deleted first.
bool CreateDesktopShortcut(const ShellIntegration::ShortcutInfo& shortcut_info,
const std::string& shortcut_template);
+// Delete any desktop shortcuts on desktop or in the application menu that have
+// been added for the extension with |extension_id| in |profile_path|.
+void DeleteDesktopShortcuts(const FilePath& profile_path,
+ const std::string& extension_id);
+
} // namespace ShellIntegrationLinux
#endif // CHROME_BROWSER_SHELL_INTEGRATION_LINUX_H_
diff --git a/chrome/browser/shell_integration_unittest.cc b/chrome/browser/shell_integration_unittest.cc
index 63921e7..31ea4a3 100644
--- a/chrome/browser/shell_integration_unittest.cc
+++ b/chrome/browser/shell_integration_unittest.cc
@@ -139,7 +139,7 @@ TEST(ShellIntegrationTest, GetDesktopShortcutTemplate) {
}
}
-TEST(ShellIntegrationTest, GetDesktopShortcutFilename) {
+TEST(ShellIntegrationTest, GetWebShortcutFilename) {
const struct {
const FilePath::CharType* path;
const char* url;
@@ -156,7 +156,7 @@ TEST(ShellIntegrationTest, GetDesktopShortcutFilename) {
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" +
test_cases[i].path,
- ShellIntegrationLinux::GetDesktopShortcutFilename(
+ ShellIntegrationLinux::GetWebShortcutFilename(
GURL(test_cases[i].url)).value()) <<
" while testing " << test_cases[i].url;
}
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index a502b5a..c2b2a34 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -127,8 +127,18 @@ void CreateShortcut(
BrowserThread::FILE,
FROM_HERE,
base::Bind(base::IgnoreResult(&CreateShortcutOnFileThread),
- profile_path,
- shortcut_info));
+ profile_path, shortcut_info));
+}
+
+void DeleteAllShortcuts(const FilePath& profile_path,
+ const std::string& extension_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ base::Bind(&internals::DeletePlatformShortcuts, profile_path,
+ extension_id));
}
bool CreateShortcutOnFileThread(
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index 253c88f..bcd445a 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -54,6 +54,11 @@ void CreateShortcut(
const FilePath& profile_path,
const ShellIntegration::ShortcutInfo& shortcut_info);
+// Delete all the shortcuts that have been created for the extension with
+// |extension_id| in the profile with |profile_path|.
+void DeleteAllShortcuts(const FilePath& profile_path,
+ const std::string& extension_id);
+
// Creates a shortcut. Must be called on the file thread. This is used to
// implement CreateShortcut() above, and can also be used directly from the
// file thread. |profile_path| is the path of the creating profile.
@@ -97,6 +102,12 @@ bool CreatePlatformShortcut(
const FilePath& profile_path,
const ShellIntegration::ShortcutInfo& shortcut_info);
+// Delete all the shortcuts we have added for this extension. This is the
+// platform specific implementation of the DeleteAllShortcuts function, and
+// is executed on the FILE thread..
+void DeletePlatformShortcuts(const FilePath& profile_path,
+ const std::string& extension_id);
+
// Sanitizes |name| and returns a version of it that is safe to use as an
// on-disk file name .
FilePath GetSanitizedFileName(const string16& name);
diff --git a/chrome/browser/web_applications/web_app_linux.cc b/chrome/browser/web_applications/web_app_linux.cc
index e26be43..56d02fbf 100644
--- a/chrome/browser/web_applications/web_app_linux.cc
+++ b/chrome/browser/web_applications/web_app_linux.cc
@@ -29,5 +29,10 @@ bool CreatePlatformShortcut(
shortcut_info, shortcut_template);
}
+void DeletePlatformShortcuts(const FilePath& profile_path,
+ const std::string& extension_id) {
+ ShellIntegrationLinux::DeleteDesktopShortcuts(profile_path, extension_id);
+}
+
} // namespace internals
} // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm
index de64f35..e4d22f0 100644
--- a/chrome/browser/web_applications/web_app_mac.mm
+++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -262,5 +262,11 @@ bool CreatePlatformShortcut(
return shortcut_creator.CreateShortcut();
}
+void DeletePlatformShortcuts(const FilePath& profile_path,
+ const std::string& extension_id) {
+ // TODO(benwells): Implement this when shortcuts / weblings are enabled on
+ // mac.
+}
+
} // namespace internals
} // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc
index f6cbbbf1..f5d85bd 100644
--- a/chrome/browser/web_applications/web_app_win.cc
+++ b/chrome/browser/web_applications/web_app_win.cc
@@ -255,6 +255,11 @@ bool CreatePlatformShortcut(
return success;
}
+void DeletePlatformShortcuts(const FilePath& profile_path,
+ const std::string& extension_id) {
+ // TODO(benwells): Implement this.
+}
+
} // namespace internals
} // namespace web_app