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

Unified Diff: chrome/browser/web_applications/web_app_win.cc

Issue 181493011: Windows: Automatically associate file types with Chrome apps. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Revert changes to about_flags (not ready yet). Created 6 years, 1 month 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/web_applications/web_app_win.cc
diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc
index 5701e5333ef80f94dde69d03af5b7db6c76558c1..a393a2039f488e60a05aeb0f78f22b4e19ace5fc 100644
--- a/chrome/browser/web_applications/web_app_win.cc
+++ b/chrome/browser/web_applications/web_app_win.cc
@@ -12,17 +12,22 @@
#include "base/logging.h"
#include "base/md5.h"
#include "base/path_service.h"
+#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/shortcut.h"
#include "base/win/windows_version.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/web_applications/update_shortcut_worker_win.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/install_util.h"
#include "chrome/installer/util/shell_util.h"
#include "chrome/installer/util/util_constants.h"
#include "content/public/browser/browser_thread.h"
+#include "extensions/common/extension.h"
+#include "net/base/mime_util.h"
#include "ui/base/win/shell.h"
#include "ui/gfx/icon_util.h"
#include "ui/gfx/image/image.h"
@@ -33,6 +38,9 @@ namespace {
const base::FilePath::CharType kIconChecksumFileExt[] =
FILE_PATH_LITERAL(".ico.md5");
+const base::FilePath::CharType kAppShimExe[] =
+ FILE_PATH_LITERAL("app_shim.exe");
+
// Calculates checksum of an icon family using MD5.
// The checksum is derived from all of the icons in the family.
void GetImageCheckSum(const gfx::ImageFamily& image, base::MD5Digest* digest) {
@@ -363,10 +371,7 @@ void OnShortcutInfoLoadedForSetRelaunchDetails(
shortcut_info.extension_id,
shortcut_info.url);
base::FilePath icon_file =
- web_app_path.Append(web_app::internals::GetSanitizedFileName(
- shortcut_info.title))
- .ReplaceExtension(FILE_PATH_LITERAL(".ico"));
-
+ web_app::internals::GetIconFilePath(web_app_path, shortcut_info.title);
content::BrowserThread::PostBlockingPoolTask(
FROM_HERE,
base::Bind(&CreateIconAndSetRelaunchDetails,
@@ -376,6 +381,136 @@ void OnShortcutInfoLoadedForSetRelaunchDetails(
hwnd));
}
+// Creates an "app shim exe" by linking or copying the generic app shim exe.
+// This is the binary that will be run when the user opens a file with this
+// application. The name and icon of the binary will be used on the Open With
+// menu. For this reason, we cannot simply launch chrome.exe. We give the app
+// shim exe the same name as the application (with no ".exe" extension), so that
+// the correct title will appear on the Open With menu. (Note: we also need a
+// separate binary per app because Windows only allows a single association with
+// each executable.)
+// |path| is the full path of the shim binary to be created.
+bool CreateAppShimBinary(const base::FilePath& path) {
+ // TODO(mgiuca): Hard-link instead of copying, if on the same file system.
+ base::FilePath chrome_binary_directory;
+ if (!PathService::Get(base::DIR_EXE, &chrome_binary_directory)) {
+ NOTREACHED();
+ return false;
+ }
+
+ base::FilePath generic_shim_path =
+ chrome_binary_directory.Append(kAppShimExe);
+ if (!base::CopyFile(generic_shim_path, path)) {
+ LOG(ERROR) << "Could not copy app shim exe to " << path.value();
+ return false;
+ }
+
+ return true;
+}
+
+// Gets the full command line for calling the shim binary. This will include a
+// placeholder "%1" argument, which Windows will substitute with the filename
+// chosen by the user.
+base::CommandLine GetAppShimCommandLine(const base::FilePath& app_shim_path,
+ const std::string& extension_id,
+ const base::FilePath& profile_path) {
+ // Get the command-line to pass to the shim (e.g., "chrome.exe --app-id=...").
+ CommandLine chrome_cmd_line = ShellIntegration::CommandLineArgsForLauncher(
+ GURL(), extension_id, profile_path);
+ chrome_cmd_line.AppendArg("%1");
+
+ // Get the command-line for calling the shim (e.g.,
+ // "app_shim [--chrome-sxs] -- --app-id=...").
+ CommandLine shim_cmd_line(app_shim_path);
+ // If this is a canary build, launch the shim in canary mode.
+ if (InstallUtil::IsChromeSxSProcess())
+ shim_cmd_line.AppendSwitch(installer::switches::kChromeSxS);
+ // Ensure all subsequent switches are treated as args to the shim.
+ shim_cmd_line.AppendArg("--");
+ for (const auto& arg : chrome_cmd_line.GetArgs())
+ shim_cmd_line.AppendArgNative(arg);
+
+ return shim_cmd_line;
+}
+
+// Gets the set of file extensions associated with a particular file handler.
+// Uses both the MIME types and extensions.
+void GetHandlerFileExtensions(const extensions::FileHandlerInfo& handler,
+ std::set<base::string16>* exts) {
+ for (const auto& mime : handler.types) {
+ std::vector<base::string16> mime_type_extensions;
+ net::GetExtensionsForMimeType(mime, &mime_type_extensions);
+ exts->insert(mime_type_extensions.begin(), mime_type_extensions.end());
+ }
+ for (const auto& ext : handler.extensions)
+ exts->insert(base::UTF8ToUTF16(ext));
+}
+
+// Creates operating system file type associations for a given app.
+// This is the platform specific implementation of the CreateFileAssociations
+// function, and is executed on the FILE thread.
+// Returns true on success, false on failure.
+bool CreateFileAssociationsForApp(
+ const std::string& extension_id,
+ const base::string16& title,
+ const base::FilePath& profile_path,
+ const extensions::FileHandlersInfo& file_handlers_info) {
+ base::FilePath web_app_path =
+ web_app::GetWebAppDataDirectory(profile_path, extension_id, GURL());
+ base::FilePath file_name = web_app::internals::GetSanitizedFileName(title);
+
+ // The progid is "chrome-APPID-HANDLERID". This is the internal name Windows
+ // will use for file associations with this application.
+ base::string16 progid_base = L"chrome-";
+ progid_base += base::UTF8ToUTF16(extension_id);
+
+ // Create the app shim binary (see CreateAppShimBinary for rationale). Get the
+ // command line for the shim.
+ base::FilePath app_shim_path = web_app_path.Append(file_name);
+ if (!CreateAppShimBinary(app_shim_path))
+ return false;
+
+ CommandLine shim_cmd_line(
+ GetAppShimCommandLine(app_shim_path, extension_id, profile_path));
+
+ // TODO(mgiuca): Get the file type name from the manifest, or generate a
+ // default one. (If this is blank, Windows will generate one of the form
+ // '<EXT> file'.)
+ base::string16 file_type_name = L"";
+
+ // TODO(mgiuca): Generate a new icon for this application's file associations
+ // that looks like a page with the application icon inside.
+ base::FilePath icon_file =
+ web_app::internals::GetIconFilePath(web_app_path, title);
+
+ // Create a separate file association (ProgId) for each handler. This allows
+ // each handler to have its own filetype name and icon, and also a different
+ // command line (so the app can see which handler was invoked).
+ size_t num_successes = 0;
+ for (const auto& handler : file_handlers_info) {
+ base::string16 progid = progid_base + L"-" + base::UTF8ToUTF16(handler.id);
+
+ std::set<base::string16> exts;
+ GetHandlerFileExtensions(handler, &exts);
+
+ if (ShellUtil::AddFileAssociations(progid, shim_cmd_line, file_type_name,
+ icon_file, exts)) {
+ ++num_successes;
+ }
+ }
+
+ if (num_successes == 0) {
+ // There were no successes; delete the shim.
+ base::DeleteFile(app_shim_path, false);
+ } else {
+ // There were some successes; tell Windows Explorer to update its cache.
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT,
+ nullptr, nullptr);
+ }
+
+ return num_successes == file_handlers_info.size();
+}
+
} // namespace
namespace web_app {
@@ -483,6 +618,12 @@ bool CreatePlatformShortcuts(
return false;
}
+ if (switches::kEnableAppsFileAssociations) {
Nico 2014/11/18 23:22:13 ..\..\chrome\browser\web_applications\web_app_win.
+ CreateFileAssociationsForApp(
+ shortcut_info.extension_id, shortcut_info.title,
+ shortcut_info.profile_path, file_handlers_info);
+ }
+
return true;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698