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

Side by Side Diff: chrome/browser/shell_integration_win.cc

Issue 14027008: Migrate app_host.exe shortcuts to chrome.exe shortcuts (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 8 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/shell_integration.h" 5 #include "chrome/browser/shell_integration.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <shobjidl.h> 8 #include <shobjidl.h>
9 #include <propkey.h> 9 #include <propkey.h>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/path_service.h" 15 #include "base/path_service.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/stringprintf.h" 17 #include "base/stringprintf.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/utf_string_conversions.h" 19 #include "base/utf_string_conversions.h"
20 #include "base/win/registry.h" 20 #include "base/win/registry.h"
21 #include "base/win/scoped_comptr.h" 21 #include "base/win/scoped_comptr.h"
22 #include "base/win/scoped_propvariant.h" 22 #include "base/win/scoped_propvariant.h"
23 #include "base/win/shortcut.h" 23 #include "base/win/shortcut.h"
24 #include "base/win/windows_version.h" 24 #include "base/win/windows_version.h"
25 #include "chrome/browser/web_applications/web_app.h" 25 #include "chrome/browser/web_applications/web_app.h"
26 #include "chrome/common/chrome_constants.h" 26 #include "chrome/common/chrome_constants.h"
27 #include "chrome/common/chrome_paths_internal.h" 27 #include "chrome/common/chrome_paths_internal.h"
28 #include "chrome/common/chrome_switches.h" 28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
29 #include "chrome/installer/setup/setup_util.h" 30 #include "chrome/installer/setup/setup_util.h"
30 #include "chrome/installer/util/browser_distribution.h" 31 #include "chrome/installer/util/browser_distribution.h"
31 #include "chrome/installer/util/create_reg_key_work_item.h" 32 #include "chrome/installer/util/create_reg_key_work_item.h"
32 #include "chrome/installer/util/install_util.h" 33 #include "chrome/installer/util/install_util.h"
33 #include "chrome/installer/util/set_reg_value_work_item.h" 34 #include "chrome/installer/util/set_reg_value_work_item.h"
34 #include "chrome/installer/util/shell_util.h" 35 #include "chrome/installer/util/shell_util.h"
35 #include "chrome/installer/util/util_constants.h" 36 #include "chrome/installer/util/util_constants.h"
36 #include "chrome/installer/util/work_item.h" 37 #include "chrome/installer/util/work_item.h"
37 #include "chrome/installer/util/work_item_list.h" 38 #include "chrome/installer/util/work_item_list.h"
38 #include "content/public/browser/browser_thread.h" 39 #include "content/public/browser/browser_thread.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 string16 app_name(dist->GetBaseAppId()); 85 string16 app_name(dist->GetBaseAppId());
85 app_name.append(kAppListAppNameSuffix); 86 app_name.append(kAppListAppNameSuffix);
86 return app_name; 87 return app_name;
87 } 88 }
88 89
89 // Gets expected app id for given Chrome (based on |command_line| and 90 // Gets expected app id for given Chrome (based on |command_line| and
90 // |is_per_user_install|). 91 // |is_per_user_install|).
91 string16 GetExpectedAppId(const CommandLine& command_line, 92 string16 GetExpectedAppId(const CommandLine& command_line,
92 bool is_per_user_install) { 93 bool is_per_user_install) {
93 base::FilePath profile_path; 94 base::FilePath profile_path;
94 if (command_line.HasSwitch(switches::kUserDataDir)) { 95 if (command_line.HasSwitch(switches::kUserDataDir)) {
koz (OOO until 15th September) 2013/04/18 02:06:08 I think this reads better if you use some intermed
calamity 2013/04/18 08:24:34 Done.
95 profile_path = 96 profile_path =
96 command_line.GetSwitchValuePath(switches::kUserDataDir).AppendASCII( 97 command_line.GetSwitchValuePath(switches::kUserDataDir);
97 chrome::kInitialProfile); 98 } else {
99 chrome::GetDefaultUserDataDirectory(&profile_path);
100 }
101
102 if (command_line.HasSwitch(switches::kProfileDirectory)) {
103 profile_path = profile_path.Append(
104 command_line.GetSwitchValuePath(switches::kProfileDirectory));
105 } else {
106 profile_path = profile_path.AppendASCII(
107 chrome::kInitialProfile);
98 } 108 }
99 109
100 string16 app_name; 110 string16 app_name;
101 if (command_line.HasSwitch(switches::kApp)) { 111 if (command_line.HasSwitch(switches::kApp)) {
102 app_name = UTF8ToUTF16(web_app::GenerateApplicationNameFromURL( 112 app_name = UTF8ToUTF16(web_app::GenerateApplicationNameFromURL(
103 GURL(command_line.GetSwitchValueASCII(switches::kApp)))); 113 GURL(command_line.GetSwitchValueASCII(switches::kApp))));
104 } else if (command_line.HasSwitch(switches::kAppId)) { 114 } else if (command_line.HasSwitch(switches::kAppId)) {
105 app_name = UTF8ToUTF16(web_app::GenerateApplicationNameFromExtensionId( 115 app_name = UTF8ToUTF16(web_app::GenerateApplicationNameFromExtensionId(
106 command_line.GetSwitchValueASCII(switches::kAppId))); 116 command_line.GetSwitchValueASCII(switches::kAppId)));
107 } else if (command_line.HasSwitch(switches::kShowAppList)) { 117 } else if (command_line.HasSwitch(switches::kShowAppList)) {
108 app_name = GetAppListAppName(); 118 app_name = GetAppListAppName();
109 } else { 119 } else {
110 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 120 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
111 app_name = ShellUtil::GetBrowserModelId(dist, is_per_user_install); 121 app_name = ShellUtil::GetBrowserModelId(dist, is_per_user_install);
112 } 122 }
113 123
114 return ShellIntegration::GetAppModelIdForProfile(app_name, profile_path); 124 return ShellIntegration::GetAppModelIdForProfile(app_name, profile_path);
115 } 125 }
116 126
117 void MigrateChromiumShortcutsCallback() { 127 void MigrateChromiumShortcutsCallback() {
118 // This should run on the file thread. 128 // This should run on the file thread.
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
120 130
121 // Get full path of chrome. 131 // Get full path of chrome.
122 base::FilePath chrome_exe; 132 base::FilePath chrome_exe;
123 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) 133 if (!PathService::Get(base::FILE_EXE, &chrome_exe))
124 return; 134 return;
125 135
136 // Get the app_host.exe path.
137 bool is_per_user_install =
138 InstallUtil::IsPerUserInstall(chrome_exe.value().c_str());
139 base::FilePath app_host_exe = GetAppHostPathForInstallationLevel(
140 is_per_user_install ? chrome_launcher_support::USER_LEVEL_INSTALLATION
141 : chrome_launcher_support::SYSTEM_LEVEL_INSTALLATION);
142
126 // Locations to check for shortcuts migration. 143 // Locations to check for shortcuts migration.
127 static const struct { 144 static const struct {
128 int location_id; 145 int location_id;
129 const wchar_t* sub_dir; 146 const wchar_t* sub_dir;
130 } kLocations[] = { 147 } kLocations[] = {
131 { 148 {
149 base::DIR_IMPLICIT_APP_SHORTCUTS,
150 NULL
151 }, {
132 base::DIR_TASKBAR_PINS, 152 base::DIR_TASKBAR_PINS,
133 NULL 153 NULL
134 }, { 154 }, {
135 base::DIR_USER_DESKTOP, 155 base::DIR_USER_DESKTOP,
136 NULL 156 NULL
137 }, { 157 }, {
138 base::DIR_START_MENU, 158 base::DIR_START_MENU,
139 NULL 159 NULL
140 }, { 160 }, {
141 base::DIR_APP_DATA, 161 base::DIR_APP_DATA,
142 L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\StartMenu" 162 L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\StartMenu"
143 } 163 }
144 }; 164 };
145 165
146 for (int i = 0; i < arraysize(kLocations); ++i) { 166 for (int i = 0; i < arraysize(kLocations); ++i) {
147 base::FilePath path; 167 base::FilePath path;
148 if (!PathService::Get(kLocations[i].location_id, &path)) { 168 if (!PathService::Get(kLocations[i].location_id, &path)) {
149 NOTREACHED(); 169 NOTREACHED();
150 continue; 170 continue;
151 } 171 }
152 172
153 if (kLocations[i].sub_dir) 173 if (kLocations[i].sub_dir)
154 path = path.Append(kLocations[i].sub_dir); 174 path = path.Append(kLocations[i].sub_dir);
155 175
156 bool check_dual_mode = (kLocations[i].location_id == base::DIR_START_MENU); 176 bool check_dual_mode = (kLocations[i].location_id == base::DIR_START_MENU);
157 ShellIntegration::MigrateShortcutsInPathInternal(chrome_exe, path, 177 bool recursive =
158 check_dual_mode); 178 (kLocations[i].location_id == base::DIR_IMPLICIT_APP_SHORTCUTS);
179 ShellIntegration::MigrateShortcutsInPathInternal(chrome_exe,
180 app_host_exe,
181 path,
182 check_dual_mode,
183 recursive);
159 } 184 }
160 } 185 }
161 186
162 ShellIntegration::DefaultWebClientState 187 ShellIntegration::DefaultWebClientState
163 GetDefaultWebClientStateFromShellUtilDefaultState( 188 GetDefaultWebClientStateFromShellUtilDefaultState(
164 ShellUtil::DefaultState default_state) { 189 ShellUtil::DefaultState default_state) {
165 switch (default_state) { 190 switch (default_state) {
166 case ShellUtil::NOT_DEFAULT: 191 case ShellUtil::NOT_DEFAULT:
167 return ShellIntegration::NOT_DEFAULT; 192 return ShellIntegration::NOT_DEFAULT;
168 case ShellUtil::IS_DEFAULT: 193 case ShellUtil::IS_DEFAULT:
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 // urgent and shouldn't delay Chrome startup. 394 // urgent and shouldn't delay Chrome startup.
370 static const int64 kMigrateChromiumShortcutsDelaySeconds = 15; 395 static const int64 kMigrateChromiumShortcutsDelaySeconds = 15;
371 BrowserThread::PostDelayedTask( 396 BrowserThread::PostDelayedTask(
372 BrowserThread::FILE, FROM_HERE, 397 BrowserThread::FILE, FROM_HERE,
373 base::Bind(&MigrateChromiumShortcutsCallback), 398 base::Bind(&MigrateChromiumShortcutsCallback),
374 base::TimeDelta::FromSeconds(kMigrateChromiumShortcutsDelaySeconds)); 399 base::TimeDelta::FromSeconds(kMigrateChromiumShortcutsDelaySeconds));
375 } 400 }
376 401
377 int ShellIntegration::MigrateShortcutsInPathInternal( 402 int ShellIntegration::MigrateShortcutsInPathInternal(
378 const base::FilePath& chrome_exe, 403 const base::FilePath& chrome_exe,
404 const base::FilePath& app_host_exe,
379 const base::FilePath& path, 405 const base::FilePath& path,
380 bool check_dual_mode) { 406 bool check_dual_mode,
407 bool recursive) {
381 DCHECK(base::win::GetVersion() >= base::win::VERSION_WIN7); 408 DCHECK(base::win::GetVersion() >= base::win::VERSION_WIN7);
382 409
410
383 // Enumerate all pinned shortcuts in the given path directly. 411 // Enumerate all pinned shortcuts in the given path directly.
384 file_util::FileEnumerator shortcuts_enum( 412 file_util::FileEnumerator shortcuts_enum(
385 path, false, // not recursive 413 path, recursive,
386 file_util::FileEnumerator::FILES, FILE_PATH_LITERAL("*.lnk")); 414 file_util::FileEnumerator::FILES);
387 415
388 bool is_per_user_install = 416 bool is_per_user_install =
389 InstallUtil::IsPerUserInstall(chrome_exe.value().c_str()); 417 InstallUtil::IsPerUserInstall(chrome_exe.value().c_str());
390 418
391 int shortcuts_migrated = 0; 419 int shortcuts_migrated = 0;
392 base::FilePath target_path; 420 base::FilePath target_path;
393 string16 arguments; 421 string16 arguments;
394 base::win::ScopedPropVariant propvariant; 422 base::win::ScopedPropVariant propvariant;
395 for (base::FilePath shortcut = shortcuts_enum.Next(); !shortcut.empty(); 423 for (base::FilePath shortcut = shortcuts_enum.Next(); !shortcut.empty();
396 shortcut = shortcuts_enum.Next()) { 424 shortcut = shortcuts_enum.Next()) {
397 // TODO(gab): Use ProgramCompare instead of comparing FilePaths below once 425 // TODO(gab): Use ProgramCompare instead of comparing FilePaths below once
398 // it is fixed to work with FilePaths with spaces. 426 // it is fixed to work with FilePaths with spaces.
399 if (!base::win::ResolveShortcut(shortcut, &target_path, &arguments) || 427 if (shortcut.Extension() != installer::kLnkExt ||
400 chrome_exe != target_path) { 428 !base::win::ResolveShortcut(shortcut, &target_path, &arguments) ||
429 (chrome_exe != target_path && app_host_exe != target_path)) {
401 continue; 430 continue;
402 } 431 }
403 CommandLine command_line(CommandLine::FromString(base::StringPrintf( 432 CommandLine command_line(CommandLine::FromString(base::StringPrintf(
404 L"\"%ls\" %ls", target_path.value().c_str(), arguments.c_str()))); 433 L"\"%ls\" %ls", target_path.value().c_str(), arguments.c_str())));
405 434
406 // Get the expected AppId for this Chrome shortcut. 435 // Get the expected AppId for this Chrome shortcut.
407 string16 expected_app_id( 436 string16 expected_app_id(
408 GetExpectedAppId(command_line, is_per_user_install)); 437 GetExpectedAppId(command_line, is_per_user_install));
409 if (expected_app_id.empty()) 438 if (expected_app_id.empty())
410 continue; 439 continue;
411 440
412 // Load the shortcut. 441 // Load the shortcut.
413 base::win::ScopedComPtr<IShellLink> shell_link; 442 base::win::ScopedComPtr<IShellLink> shell_link;
414 base::win::ScopedComPtr<IPersistFile> persist_file; 443 base::win::ScopedComPtr<IPersistFile> persist_file;
415 if (FAILED(shell_link.CreateInstance(CLSID_ShellLink, NULL, 444 if (FAILED(shell_link.CreateInstance(CLSID_ShellLink, NULL,
416 CLSCTX_INPROC_SERVER)) || 445 CLSCTX_INPROC_SERVER)) ||
417 FAILED(persist_file.QueryFrom(shell_link)) || 446 FAILED(persist_file.QueryFrom(shell_link)) ||
418 FAILED(persist_file->Load(shortcut.value().c_str(), STGM_READ))) { 447 FAILED(persist_file->Load(shortcut.value().c_str(), STGM_READ))) {
419 DLOG(WARNING) << "Failed loading shortcut at " << shortcut.value(); 448 DLOG(WARNING) << "Failed loading shortcut at " << shortcut.value();
420 continue; 449 continue;
421 } 450 }
422 451
423 // Any properties that need to be updated on the shortcut will be stored in 452 // Any properties that need to be updated on the shortcut will be stored in
424 // |updated_properties|. 453 // |updated_properties|.
425 base::win::ShortcutProperties updated_properties; 454 base::win::ShortcutProperties updated_properties;
426 455
456 // Migrate app_host.exe shortcuts to chrome.exe
457 if (target_path == app_host_exe) {
458 updated_properties.set_target(chrome_exe);
459 }
460
427 // Validate the existing app id for the shortcut. 461 // Validate the existing app id for the shortcut.
428 base::win::ScopedComPtr<IPropertyStore> property_store; 462 base::win::ScopedComPtr<IPropertyStore> property_store;
429 propvariant.Reset(); 463 propvariant.Reset();
430 if (FAILED(property_store.QueryFrom(shell_link)) || 464 if (FAILED(property_store.QueryFrom(shell_link)) ||
431 property_store->GetValue(PKEY_AppUserModel_ID, 465 property_store->GetValue(PKEY_AppUserModel_ID,
432 propvariant.Receive()) != S_OK) { 466 propvariant.Receive()) != S_OK) {
433 // When in doubt, prefer not updating the shortcut. 467 // When in doubt, prefer not updating the shortcut.
434 NOTREACHED(); 468 NOTREACHED();
435 continue; 469 continue;
436 } else { 470 } else {
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 } 544 }
511 545
512 shortcut = shortcut.Append(shortcut_name).Append(shortcut_name + 546 shortcut = shortcut.Append(shortcut_name).Append(shortcut_name +
513 installer::kLnkExt); 547 installer::kLnkExt);
514 if (file_util::PathExists(shortcut)) 548 if (file_util::PathExists(shortcut))
515 return shortcut; 549 return shortcut;
516 } 550 }
517 551
518 return base::FilePath(); 552 return base::FilePath();
519 } 553 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698