Commit 05b50bd9 authored by Jay Harris's avatar Jay Harris Committed by Commit Bot

WebApps: Adds support for handling mimetypes in WebApps on Linux.

This lets web apps that can handle files show up in the
open-with menu on Linux.

Note: This is still experimental and hidden behind the
NativeFileSystemAPI and FileHandlingAPI flags.

In addition, some work needs to be done to register custom mimetypes
with the operating system as in:
https://specifications.freedesktop.org/shared-mime-info-spec/latest/ar01s02.html

Bug: 829689
Change-Id: I92bcc07cb5dffaa715c409bc6cf07c8410db34ef
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1833027
Commit-Queue: Jay Harris <harrisjay@chromium.org>
Reviewed-by: default avatarThomas Anderson <thomasanderson@chromium.org>
Reviewed-by: default avatarAlexey Baskakov <loyso@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#710593}
parent 90f9556a
...@@ -497,8 +497,7 @@ std::vector<base::FilePath> GetExistingProfileShortcutFilenames( ...@@ -497,8 +497,7 @@ std::vector<base::FilePath> GetExistingProfileShortcutFilenames(
return shortcut_paths; return shortcut_paths;
} }
std::string GetDesktopFileContents( std::string GetDesktopFileContents(const base::FilePath& chrome_exe_path,
const base::FilePath& chrome_exe_path,
const std::string& app_name, const std::string& app_name,
const GURL& url, const GURL& url,
const std::string& extension_id, const std::string& extension_id,
...@@ -506,12 +505,14 @@ std::string GetDesktopFileContents( ...@@ -506,12 +505,14 @@ std::string GetDesktopFileContents(
const std::string& icon_name, const std::string& icon_name,
const base::FilePath& profile_path, const base::FilePath& profile_path,
const std::string& categories, const std::string& categories,
const std::string& mime_type,
bool no_display) { bool no_display) {
base::CommandLine cmd_line = shell_integration::CommandLineArgsForLauncher( base::CommandLine cmd_line = shell_integration::CommandLineArgsForLauncher(
url, extension_id, profile_path); url, extension_id, profile_path);
cmd_line.SetProgram(chrome_exe_path); cmd_line.SetProgram(chrome_exe_path);
return GetDesktopFileContentsForCommand(cmd_line, app_name, url, title, return GetDesktopFileContentsForCommand(cmd_line, app_name, url, title,
icon_name, categories, no_display); icon_name, categories, mime_type,
no_display);
} }
std::string GetDesktopFileContentsForCommand( std::string GetDesktopFileContentsForCommand(
...@@ -521,6 +522,7 @@ std::string GetDesktopFileContentsForCommand( ...@@ -521,6 +522,7 @@ std::string GetDesktopFileContentsForCommand(
const base::string16& title, const base::string16& title,
const std::string& icon_name, const std::string& icon_name,
const std::string& categories, const std::string& categories,
const std::string& mime_type,
bool no_display) { bool no_display) {
#if defined(USE_GLIB) #if defined(USE_GLIB)
// Although not required by the spec, Nautilus on Ubuntu Karmic creates its // Although not required by the spec, Nautilus on Ubuntu Karmic creates its
...@@ -565,6 +567,13 @@ std::string GetDesktopFileContentsForCommand( ...@@ -565,6 +567,13 @@ std::string GetDesktopFileContentsForCommand(
key_file, kDesktopEntry, "Categories", categories.c_str()); key_file, kDesktopEntry, "Categories", categories.c_str());
} }
// Set the "MimeType" key.
if (!mime_type.empty() && mime_type.find("\n") == std::string::npos &&
mime_type.find("\r") == std::string::npos) {
g_key_file_set_string(key_file, kDesktopEntry, "MimeType",
mime_type.c_str());
}
// Set the "NoDisplay" key. // Set the "NoDisplay" key.
if (no_display) if (no_display)
g_key_file_set_string(key_file, kDesktopEntry, "NoDisplay", "true"); g_key_file_set_string(key_file, kDesktopEntry, "NoDisplay", "true");
......
...@@ -65,6 +65,7 @@ std::string GetDesktopFileContents(const base::FilePath& chrome_exe_path, ...@@ -65,6 +65,7 @@ std::string GetDesktopFileContents(const base::FilePath& chrome_exe_path,
const std::string& icon_name, const std::string& icon_name,
const base::FilePath& profile_path, const base::FilePath& profile_path,
const std::string& categories, const std::string& categories,
const std::string& mime_type,
bool no_display); bool no_display);
// Returns contents for .desktop file that executes command_line. This is a more // Returns contents for .desktop file that executes command_line. This is a more
...@@ -77,6 +78,7 @@ std::string GetDesktopFileContentsForCommand( ...@@ -77,6 +78,7 @@ std::string GetDesktopFileContentsForCommand(
const base::string16& title, const base::string16& title,
const std::string& icon_name, const std::string& icon_name,
const std::string& categories, const std::string& categories,
const std::string& mime_type,
bool no_display); bool no_display);
// Returns contents for .directory file named |title| with icon |icon_name|. If // Returns contents for .directory file named |title| with icon |icon_name|. If
......
...@@ -330,11 +330,12 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -330,11 +330,12 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
const char* const title; const char* const title;
const char* const icon_name; const char* const icon_name;
const char* const categories; const char* const categories;
const char* const mime_type;
bool nodisplay; bool nodisplay;
const char* const expected_output; const char* const expected_output;
} test_cases[] = { } test_cases[] = {
// Real-world case. // Real-world case.
{"http://gmail.com", "GMail", "chrome-http__gmail.com", "", false, {"http://gmail.com", "GMail", "chrome-http__gmail.com", "", "", false,
"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n" "[Desktop Entry]\n"
...@@ -347,7 +348,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -347,7 +348,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"StartupWMClass=gmail.com\n"}, "StartupWMClass=gmail.com\n"},
// Make sure that empty icons are replaced by the chrome icon. // Make sure that empty icons are replaced by the chrome icon.
{"http://gmail.com", "GMail", "", "", false, {"http://gmail.com", "GMail", "", "", "", false,
"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n" "[Desktop Entry]\n"
...@@ -365,7 +366,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -365,7 +366,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
// Test adding categories and NoDisplay=true. // Test adding categories and NoDisplay=true.
{"http://gmail.com", "GMail", "chrome-http__gmail.com", {"http://gmail.com", "GMail", "chrome-http__gmail.com",
"Graphics;Education;", true, "Graphics;Education;", "", true,
"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n" "[Desktop Entry]\n"
...@@ -381,7 +382,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -381,7 +382,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
// Now we're starting to be more evil... // Now we're starting to be more evil...
{"http://evil.com/evil --join-the-b0tnet", "Ownz0red\nExec=rm -rf /", {"http://evil.com/evil --join-the-b0tnet", "Ownz0red\nExec=rm -rf /",
"chrome-http__evil.com_evil", "", false, "chrome-http__evil.com_evil", "", "", false,
"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n" "[Desktop Entry]\n"
...@@ -394,7 +395,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -394,7 +395,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"Icon=chrome-http__evil.com_evil\n" "Icon=chrome-http__evil.com_evil\n"
"StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"}, "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"},
{"http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red", {"http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
"Innocent Title", "chrome-http__evil.com_evil", "", false, "Innocent Title", "chrome-http__evil.com_evil", "", "", false,
"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n" "[Desktop Entry]\n"
...@@ -412,7 +413,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -412,7 +413,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20" "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20"
"rm%20-rf%20$HOME%20%3Eownz0red\n"}, "rm%20-rf%20$HOME%20%3Eownz0red\n"},
{"http://evil.com/evil | cat `echo ownz0red` >/dev/null", {"http://evil.com/evil | cat `echo ownz0red` >/dev/null",
"Innocent Title", "chrome-http__evil.com_evil", "", false, "Innocent Title", "chrome-http__evil.com_evil", "", "", false,
"#!/usr/bin/env xdg-open\n" "#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n" "[Desktop Entry]\n"
...@@ -426,7 +427,36 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -426,7 +427,36 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"Icon=chrome-http__evil.com_evil\n" "Icon=chrome-http__evil.com_evil\n"
"StartupWMClass=evil.com__evil%20%7C%20cat%20%60echo%20ownz0red" "StartupWMClass=evil.com__evil%20%7C%20cat%20%60echo%20ownz0red"
"%60%20%3E_dev_null\n"}, "%60%20%3E_dev_null\n"},
}; // Test setting mime type
{"https://paint.app", "Paint", "chrome-https__paint.app", "Image",
"image/png;image/jpg", false,
"#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n"
"Version=1.0\n"
"Terminal=false\n"
"Type=Application\n"
"Name=Paint\n"
"Exec=/opt/google/chrome/google-chrome --app=https://paint.app/\n"
"Icon=chrome-https__paint.app\n"
"Categories=Image\n"
"MimeType=image/png;image/jpg\n"
"StartupWMClass=paint.app\n"},
// Test evil mime type.
{"https://paint.app", "Evil Paint", "chrome-https__paint.app", "Image",
"image/png\nExec=rm -rf /", false,
"#!/usr/bin/env xdg-open\n"
"[Desktop Entry]\n"
"Version=1.0\n"
"Terminal=false\n"
"Type=Application\n"
"Name=Evil Paint\n"
"Exec=/opt/google/chrome/google-chrome --app=https://paint.app/\n"
"Icon=chrome-https__paint.app\n"
"Categories=Image\n"
"StartupWMClass=paint.app\n"}};
for (size_t i = 0; i < base::size(test_cases); i++) { for (size_t i = 0; i < base::size(test_cases); i++) {
SCOPED_TRACE(i); SCOPED_TRACE(i);
...@@ -435,12 +465,9 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) { ...@@ -435,12 +465,9 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
GetDesktopFileContents( GetDesktopFileContents(
kChromeExePath, kChromeExePath,
web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)), web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)),
GURL(test_cases[i].url), GURL(test_cases[i].url), std::string(),
std::string(), base::ASCIIToUTF16(test_cases[i].title), test_cases[i].icon_name,
base::ASCIIToUTF16(test_cases[i].title), base::FilePath(), test_cases[i].categories, test_cases[i].mime_type,
test_cases[i].icon_name,
base::FilePath(),
test_cases[i].categories,
test_cases[i].nodisplay)); test_cases[i].nodisplay));
} }
} }
...@@ -461,13 +488,9 @@ TEST(ShellIntegrationTest, GetDesktopFileContentsAppList) { ...@@ -461,13 +488,9 @@ TEST(ShellIntegrationTest, GetDesktopFileContentsAppList) {
"Categories=Network;WebBrowser;\n" "Categories=Network;WebBrowser;\n"
"StartupWMClass=chrome-app-list\n", "StartupWMClass=chrome-app-list\n",
GetDesktopFileContentsForCommand( GetDesktopFileContentsForCommand(
command_line, command_line, "chrome-app-list", GURL(),
"chrome-app-list", base::ASCIIToUTF16("Chrome App Launcher"), "chrome_app_list",
GURL(), "Network;WebBrowser;", "", false));
base::ASCIIToUTF16("Chrome App Launcher"),
"chrome_app_list",
"Network;WebBrowser;",
false));
} }
TEST(ShellIntegrationTest, GetDirectoryFileContents) { TEST(ShellIntegrationTest, GetDirectoryFileContents) {
......
...@@ -85,6 +85,7 @@ source_set("components") { ...@@ -85,6 +85,7 @@ source_set("components") {
if (is_desktop_linux) { if (is_desktop_linux) {
# Desktop linux, doesn't count ChromeOS. # Desktop linux, doesn't count ChromeOS.
sources += [ sources += [
"web_app_file_handler_registration_linux.cc",
"web_app_shortcut_linux.cc", "web_app_shortcut_linux.cc",
"web_app_shortcut_linux.h", "web_app_shortcut_linux.h",
] ]
......
...@@ -11,43 +11,35 @@ ...@@ -11,43 +11,35 @@
namespace web_app { namespace web_app {
FileHandlerManager::FileHandlerManager(Profile* profile) FileHandlerManager::FileHandlerManager(Profile* profile)
: profile_(profile), registrar_observer_(this) {} : profile_(profile), registrar_observer_(this), shortcut_observer_(this) {}
FileHandlerManager::~FileHandlerManager() = default; FileHandlerManager::~FileHandlerManager() = default;
void FileHandlerManager::SetSubsystems(AppRegistrar* registrar) { void FileHandlerManager::SetSubsystems(AppRegistrar* registrar,
AppShortcutManager* shortcut_manager) {
registrar_ = registrar; registrar_ = registrar;
registrar_observer_.Add(registrar); shortcut_manager_ = shortcut_manager;
} }
void FileHandlerManager::OnWebAppInstalled(const AppId& installed_app_id) { void FileHandlerManager::Start() {
if (!base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI) || DCHECK(registrar_);
!OsSupportsWebAppFileHandling()) DCHECK(shortcut_manager_);
return;
std::string app_name = registrar_->GetAppShortName(installed_app_id); registrar_observer_.Add(registrar_);
const std::vector<apps::FileHandlerInfo>* file_handlers = shortcut_observer_.Add(shortcut_manager_);
GetFileHandlers(installed_app_id);
if (!file_handlers)
return;
std::set<std::string> file_extensions =
GetFileExtensionsFromFileHandlers(*file_handlers);
std::set<std::string> mime_types =
GetMimeTypesFromFileHandlers(*file_handlers);
RegisterFileHandlersForWebApp(installed_app_id, app_name, *profile_,
file_extensions, mime_types);
} }
void FileHandlerManager::OnWebAppUninstalled(const AppId& installed_app_id) { void FileHandlerManager::OnWebAppUninstalled(const AppId& installed_app_id) {
if (base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI) && if (base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI) &&
OsSupportsWebAppFileHandling()) { OsSupportsWebAppFileHandling()) {
UnregisterFileHandlersForWebApp(installed_app_id, *profile_); UnregisterFileHandlersForWebApp(installed_app_id, profile_);
} }
} }
void FileHandlerManager::OnWebAppProfileWillBeDeleted(const AppId& app_id) { void FileHandlerManager::OnWebAppProfileWillBeDeleted(const AppId& app_id) {
if (base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI) && if (base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI) &&
OsSupportsWebAppFileHandling()) { OsSupportsWebAppFileHandling()) {
UnregisterFileHandlersForWebApp(app_id, *profile_); UnregisterFileHandlersForWebApp(app_id, profile_);
} }
} }
...@@ -55,6 +47,29 @@ void FileHandlerManager::OnAppRegistrarDestroyed() { ...@@ -55,6 +47,29 @@ void FileHandlerManager::OnAppRegistrarDestroyed() {
registrar_observer_.RemoveAll(); registrar_observer_.RemoveAll();
} }
void FileHandlerManager::OnShortcutsCreated(const AppId& installed_app_id) {
if (!base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI) ||
!OsSupportsWebAppFileHandling()) {
return;
}
std::string app_name = registrar_->GetAppShortName(installed_app_id);
const std::vector<apps::FileHandlerInfo>* file_handlers =
GetFileHandlers(installed_app_id);
if (!file_handlers)
return;
std::set<std::string> file_extensions =
GetFileExtensionsFromFileHandlers(*file_handlers);
std::set<std::string> mime_types =
GetMimeTypesFromFileHandlers(*file_handlers);
RegisterFileHandlersForWebApp(installed_app_id, app_name, profile_,
file_extensions, mime_types);
}
void FileHandlerManager::OnShortcutManagerDestroyed() {
shortcut_observer_.RemoveAll();
}
std::set<std::string> GetFileExtensionsFromFileHandlers( std::set<std::string> GetFileExtensionsFromFileHandlers(
const std::vector<apps::FileHandlerInfo>& file_handlers) { const std::vector<apps::FileHandlerInfo>& file_handlers) {
std::set<std::string> file_extensions; std::set<std::string> file_extensions;
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/components/app_registrar_observer.h" #include "chrome/browser/web_applications/components/app_registrar_observer.h"
#include "chrome/browser/web_applications/components/app_shortcut_manager.h"
#include "chrome/browser/web_applications/components/app_shortcut_observer.h"
#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "components/services/app_service/public/cpp/file_handler_info.h" #include "components/services/app_service/public/cpp/file_handler_info.h"
...@@ -20,13 +22,16 @@ class Profile; ...@@ -20,13 +22,16 @@ class Profile;
namespace web_app { namespace web_app {
class FileHandlerManager : public AppRegistrarObserver { class FileHandlerManager : public AppRegistrarObserver,
public AppShortcutObserver {
public: public:
explicit FileHandlerManager(Profile* profile); explicit FileHandlerManager(Profile* profile);
~FileHandlerManager() override; ~FileHandlerManager() override;
// |registrar| is used to observe OnWebAppInstalled/Uninstalled events. // |registrar| is used to observe OnWebAppInstalled/Uninstalled events.
void SetSubsystems(AppRegistrar* registrar); void SetSubsystems(AppRegistrar* registrar,
AppShortcutManager* shortcut_manager);
void Start();
// Gets all file handlers for |app_id|. |nullptr| if the app has no file // Gets all file handlers for |app_id|. |nullptr| if the app has no file
// handlers. // handlers.
...@@ -40,14 +45,19 @@ class FileHandlerManager : public AppRegistrarObserver { ...@@ -40,14 +45,19 @@ class FileHandlerManager : public AppRegistrarObserver {
private: private:
Profile* const profile_; Profile* const profile_;
AppRegistrar* registrar_ = nullptr; AppRegistrar* registrar_ = nullptr;
AppShortcutManager* shortcut_manager_ = nullptr;
// AppRegistrarObserver: // AppRegistrarObserver:
void OnWebAppInstalled(const AppId& app_id) override;
void OnWebAppUninstalled(const AppId& app_id) override; void OnWebAppUninstalled(const AppId& app_id) override;
void OnWebAppProfileWillBeDeleted(const AppId& app_id) override; void OnWebAppProfileWillBeDeleted(const AppId& app_id) override;
void OnAppRegistrarDestroyed() override; void OnAppRegistrarDestroyed() override;
// AppShortcutObserver:
void OnShortcutsCreated(const AppId& app_id) override;
void OnShortcutManagerDestroyed() override;
ScopedObserver<AppRegistrar, AppRegistrarObserver> registrar_observer_; ScopedObserver<AppRegistrar, AppRegistrarObserver> registrar_observer_;
ScopedObserver<AppShortcutManager, AppShortcutObserver> shortcut_observer_;
DISALLOW_COPY_AND_ASSIGN(FileHandlerManager); DISALLOW_COPY_AND_ASSIGN(FileHandlerManager);
}; };
......
...@@ -9,22 +9,27 @@ ...@@ -9,22 +9,27 @@
namespace web_app { namespace web_app {
#if !defined(OS_WIN) // This block defines stub implementations of OS specific methods for
// FileHandling. Currently, Windows and Desktop Linux (but not Chrome OS) have
// their own implementations.
//
// Note: Because OS_LINUX includes OS_CHROMEOS be sure to use the stub on
// OS_CHROMEOS.
#if !defined(OS_WIN) && !(defined(OS_LINUX) && !defined(OS_CHROMEOS))
bool OsSupportsWebAppFileHandling() { bool OsSupportsWebAppFileHandling() {
return false; return false;
} }
void RegisterFileHandlersForWebApp(const AppId& app_id, void RegisterFileHandlersForWebApp(const AppId& app_id,
const std::string& app_name, const std::string& app_name,
const Profile& profile, Profile* profile,
const std::set<std::string>& file_extensions, const std::set<std::string>& file_extensions,
const std::set<std::string>& mime_types) { const std::set<std::string>& mime_types) {
DCHECK(OsSupportsWebAppFileHandling()); DCHECK(OsSupportsWebAppFileHandling());
// Stub function for OS's that don't support Web App file handling yet. // Stub function for OS's that don't support Web App file handling yet.
} }
void UnregisterFileHandlersForWebApp(const AppId& app_id, void UnregisterFileHandlersForWebApp(const AppId& app_id, Profile* profile) {
const Profile& profile) {
DCHECK(OsSupportsWebAppFileHandling()); DCHECK(OsSupportsWebAppFileHandling());
// Stub function for OS's that don't support Web App file handling yet. // Stub function for OS's that don't support Web App file handling yet.
} }
......
...@@ -22,14 +22,13 @@ bool OsSupportsWebAppFileHandling(); ...@@ -22,14 +22,13 @@ bool OsSupportsWebAppFileHandling();
// This may also involve creating a shim app to launch Chrome from. // This may also involve creating a shim app to launch Chrome from.
void RegisterFileHandlersForWebApp(const AppId& app_id, void RegisterFileHandlersForWebApp(const AppId& app_id,
const std::string& app_name, const std::string& app_name,
const Profile& profile, Profile* profile,
const std::set<std::string>& file_extensions, const std::set<std::string>& file_extensions,
const std::set<std::string>& mime_types); const std::set<std::string>& mime_types);
// Undo the file extensions registration for the PWA with specified |app_id|. // Undo the file extensions registration for the PWA with specified |app_id|.
// If a shim app was required, also removes the shim app. // If a shim app was required, also removes the shim app.
void UnregisterFileHandlersForWebApp(const AppId& app_id, void UnregisterFileHandlersForWebApp(const AppId& app_id, Profile* profile);
const Profile& profile);
} // namespace web_app } // namespace web_app
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/web_applications/components/web_app_file_handler_registration.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "chrome/browser/web_applications/components/app_shortcut_manager.h"
#include "chrome/browser/web_applications/components/web_app_provider_base.h"
#include "chrome/browser/web_applications/components/web_app_shortcut.h"
namespace web_app {
namespace {
void OnShortcutInfoReceived(const std::set<std::string> mime_types,
std::unique_ptr<ShortcutInfo> info) {
for (const auto& mime_type : mime_types)
info->mime_types.push_back(mime_type);
base::FilePath shortcut_data_dir = internals::GetShortcutDataDir(*info);
ShortcutLocations locations;
locations.applications_menu_location = APP_MENU_LOCATION_SUBDIR_CHROMEAPPS;
internals::ScheduleCreatePlatformShortcuts(
std::move(shortcut_data_dir), locations,
ShortcutCreationReason::SHORTCUT_CREATION_BY_USER, std::move(info),
base::DoNothing());
}
} // namespace
bool OsSupportsWebAppFileHandling() {
return true;
}
void RegisterFileHandlersForWebApp(const AppId& app_id,
const std::string& app_name,
Profile* profile,
const std::set<std::string>& file_extensions,
const std::set<std::string>& mime_types) {
AppShortcutManager& shortcut_manager =
WebAppProviderBase::GetProviderBase(profile)->shortcut_manager();
shortcut_manager.GetShortcutInfoForApp(
app_id, base::BindOnce(OnShortcutInfoReceived, mime_types));
}
void UnregisterFileHandlersForWebApp(const AppId& app_id, Profile* profile) {
// TODO(harrisjay): Add support for unregistering file handlers.
}
} // namespace web_app
...@@ -14,14 +14,13 @@ bool OsSupportsWebAppFileHandling() { ...@@ -14,14 +14,13 @@ bool OsSupportsWebAppFileHandling() {
void RegisterFileHandlersForWebApp(const AppId& app_id, void RegisterFileHandlersForWebApp(const AppId& app_id,
const std::string& app_name, const std::string& app_name,
const Profile& profile, Profile* profile,
const std::set<std::string>& file_extensions, const std::set<std::string>& file_extensions,
const std::set<std::string>& mime_types) { const std::set<std::string>& mime_types) {
// TODO(davidbienvenu): Setup shim app and windows registry for this |app_id|. // TODO(davidbienvenu): Setup shim app and windows registry for this |app_id|.
} }
void UnregisterFileHandlersForWebApp(const AppId& app_id, void UnregisterFileHandlersForWebApp(const AppId& app_id, Profile* profile) {
const Profile& profile) {
// TODO(davidbienvenu): Cleanup windows registry entries for this // TODO(davidbienvenu): Cleanup windows registry entries for this
// |app_id|. // |app_id|.
} }
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_SHORTCUT_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_SHORTCUT_H_
#include <memory> #include <memory>
#include <string>
#include <vector>
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
...@@ -38,6 +40,7 @@ struct ShortcutInfo { ...@@ -38,6 +40,7 @@ struct ShortcutInfo {
base::FilePath profile_path; base::FilePath profile_path;
std::string profile_name; std::string profile_name;
std::string version_for_display; std::string version_for_display;
std::vector<std::string> mime_types;
private: private:
// Since gfx::ImageFamily |favicon| has a non-thread-safe reference count in // Since gfx::ImageFamily |favicon| has a non-thread-safe reference count in
......
...@@ -270,7 +270,7 @@ bool CreateDesktopShortcut( ...@@ -270,7 +270,7 @@ bool CreateDesktopShortcut(
std::string contents = shell_integration_linux::GetDesktopFileContents( std::string contents = shell_integration_linux::GetDesktopFileContents(
chrome_exe_path, app_name, shortcut_info.url, chrome_exe_path, app_name, shortcut_info.url,
shortcut_info.extension_id, shortcut_info.title, icon_name, shortcut_info.extension_id, shortcut_info.title, icon_name,
shortcut_info.profile_path, "", false); shortcut_info.profile_path, "", "", false);
success = CreateShortcutOnDesktop(shortcut_filename, contents); success = CreateShortcutOnDesktop(shortcut_filename, contents);
} }
...@@ -299,6 +299,7 @@ bool CreateDesktopShortcut( ...@@ -299,6 +299,7 @@ bool CreateDesktopShortcut(
std::string contents = shell_integration_linux::GetDesktopFileContents( std::string contents = shell_integration_linux::GetDesktopFileContents(
chrome_exe_path, app_name, shortcut_info.url, shortcut_info.extension_id, chrome_exe_path, app_name, shortcut_info.url, shortcut_info.extension_id,
shortcut_info.title, icon_name, shortcut_info.profile_path, "", shortcut_info.title, icon_name, shortcut_info.profile_path, "",
base::JoinString(shortcut_info.mime_types, ";"),
creation_locations.applications_menu_location == creation_locations.applications_menu_location ==
web_app::APP_MENU_LOCATION_HIDDEN); web_app::APP_MENU_LOCATION_HIDDEN);
success = CreateShortcutInApplicationsMenu(shortcut_filename, contents, success = CreateShortcutInApplicationsMenu(shortcut_filename, contents,
......
...@@ -224,7 +224,8 @@ void WebAppProvider::ConnectSubsystems() { ...@@ -224,7 +224,8 @@ void WebAppProvider::ConnectSubsystems() {
system_web_app_manager_->SetSubsystems(pending_app_manager_.get(), system_web_app_manager_->SetSubsystems(pending_app_manager_.get(),
registrar_.get(), ui_manager_.get()); registrar_.get(), ui_manager_.get());
web_app_policy_manager_->SetSubsystems(pending_app_manager_.get()); web_app_policy_manager_->SetSubsystems(pending_app_manager_.get());
file_handler_manager_->SetSubsystems(registrar_.get()); file_handler_manager_->SetSubsystems(registrar_.get(),
shortcut_manager_.get());
shortcut_manager_->SetSubsystems(registrar_.get()); shortcut_manager_->SetSubsystems(registrar_.get());
connected_ = true; connected_ = true;
...@@ -246,6 +247,7 @@ void WebAppProvider::OnRegistryControllerReady() { ...@@ -246,6 +247,7 @@ void WebAppProvider::OnRegistryControllerReady() {
system_web_app_manager_->Start(); system_web_app_manager_->Start();
} }
manifest_update_manager_->Start(); manifest_update_manager_->Start();
file_handler_manager_->Start();
on_registry_ready_.Signal(); on_registry_ready_.Signal();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment