diff options
-rw-r--r-- | chrome/browser/extensions/app_shortcut_manager.cc | 33 | ||||
-rw-r--r-- | chrome/browser/shell_integration_linux.cc | 65 | ||||
-rw-r--r-- | chrome/browser/shell_integration_linux.h | 18 | ||||
-rw-r--r-- | chrome/browser/shell_integration_unittest.cc | 4 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app.cc | 14 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app.h | 11 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_linux.cc | 5 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac.mm | 6 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_win.cc | 5 |
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 |