| OLD | NEW |
| 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 <shlwapi.h> | 8 #include <shlwapi.h> |
| 9 #include <shobjidl.h> | 9 #include <shobjidl.h> |
| 10 #include <propkey.h> // Needs to come after shobjidl.h. | 10 #include <propkey.h> // Needs to come after shobjidl.h. |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 app_name = GetAppListAppName(); | 147 app_name = GetAppListAppName(); |
| 148 } else { | 148 } else { |
| 149 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 149 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 150 app_name = ShellUtil::GetBrowserModelId(dist, is_per_user_install); | 150 app_name = ShellUtil::GetBrowserModelId(dist, is_per_user_install); |
| 151 } | 151 } |
| 152 DCHECK(!app_name.empty()); | 152 DCHECK(!app_name.empty()); |
| 153 | 153 |
| 154 return ShellIntegration::GetAppModelIdForProfile(app_name, profile_path); | 154 return ShellIntegration::GetAppModelIdForProfile(app_name, profile_path); |
| 155 } | 155 } |
| 156 | 156 |
| 157 void MigrateChromiumShortcutsCallback() { | 157 void MigrateTaskbarPinsCallback() { |
| 158 // This should run on the file thread. | 158 // This should run on the file thread. |
| 159 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 159 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 160 | 160 |
| 161 // Get full path of chrome. | 161 // Get full path of chrome. |
| 162 base::FilePath chrome_exe; | 162 base::FilePath chrome_exe; |
| 163 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) | 163 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) |
| 164 return; | 164 return; |
| 165 | 165 |
| 166 // Locations to check for shortcuts migration. | 166 base::FilePath pins_path; |
| 167 static const struct { | 167 if (!PathService::Get(base::DIR_TASKBAR_PINS, &pins_path)) { |
| 168 int location_id; | 168 NOTREACHED(); |
| 169 const wchar_t* sub_dir; | 169 return; |
| 170 } kLocations[] = { | 170 } |
| 171 { | |
| 172 base::DIR_TASKBAR_PINS, | |
| 173 NULL | |
| 174 }, { | |
| 175 base::DIR_USER_DESKTOP, | |
| 176 NULL | |
| 177 }, { | |
| 178 base::DIR_START_MENU, | |
| 179 NULL | |
| 180 }, { | |
| 181 base::DIR_APP_DATA, | |
| 182 L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\StartMenu" | |
| 183 } | |
| 184 }; | |
| 185 | 171 |
| 186 for (size_t i = 0; i < arraysize(kLocations); ++i) { | 172 ShellIntegration::MigrateShortcutsInPathInternal(chrome_exe, pins_path); |
| 187 base::FilePath path; | |
| 188 if (!PathService::Get(kLocations[i].location_id, &path)) { | |
| 189 NOTREACHED(); | |
| 190 continue; | |
| 191 } | |
| 192 | |
| 193 if (kLocations[i].sub_dir) | |
| 194 path = path.Append(kLocations[i].sub_dir); | |
| 195 | |
| 196 // Clear |dual_mode| property from taskbar pins as those are user-level | |
| 197 // shortcuts which aren't handled by the installer. | |
| 198 bool clear_dual_mode = kLocations[i].location_id == base::DIR_TASKBAR_PINS; | |
| 199 ShellIntegration::MigrateShortcutsInPathInternal(chrome_exe, path, | |
| 200 clear_dual_mode); | |
| 201 } | |
| 202 } | 173 } |
| 203 | 174 |
| 204 // Windows 8 introduced a new protocol->executable binding system which cannot | 175 // Windows 8 introduced a new protocol->executable binding system which cannot |
| 205 // be retrieved in the HKCR registry subkey method implemented below. We call | 176 // be retrieved in the HKCR registry subkey method implemented below. We call |
| 206 // AssocQueryString with the new Win8-only flag ASSOCF_IS_PROTOCOL instead. | 177 // AssocQueryString with the new Win8-only flag ASSOCF_IS_PROTOCOL instead. |
| 207 base::string16 GetAppForProtocolUsingAssocQuery(const GURL& url) { | 178 base::string16 GetAppForProtocolUsingAssocQuery(const GURL& url) { |
| 208 base::string16 url_scheme = base::ASCIIToUTF16(url.scheme()); | 179 base::string16 url_scheme = base::ASCIIToUTF16(url.scheme()); |
| 209 // Don't attempt to query protocol association on an empty string. | 180 // Don't attempt to query protocol association on an empty string. |
| 210 if (url_scheme.empty()) | 181 if (url_scheme.empty()) |
| 211 return base::string16(); | 182 return base::string16(); |
| (...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 ShellUtil::GetBrowserModelId(dist, | 473 ShellUtil::GetBrowserModelId(dist, |
| 503 InstallUtil::IsPerUserInstall(chrome_exe)), | 474 InstallUtil::IsPerUserInstall(chrome_exe)), |
| 504 profile_path); | 475 profile_path); |
| 505 } | 476 } |
| 506 | 477 |
| 507 base::string16 ShellIntegration::GetAppListAppModelIdForProfile( | 478 base::string16 ShellIntegration::GetAppListAppModelIdForProfile( |
| 508 const base::FilePath& profile_path) { | 479 const base::FilePath& profile_path) { |
| 509 return GetAppModelIdForProfile(GetAppListAppName(), profile_path); | 480 return GetAppModelIdForProfile(GetAppListAppName(), profile_path); |
| 510 } | 481 } |
| 511 | 482 |
| 512 void ShellIntegration::MigrateChromiumShortcuts() { | 483 void ShellIntegration::MigrateTaskbarPins() { |
| 513 if (base::win::GetVersion() < base::win::VERSION_WIN7) | 484 if (base::win::GetVersion() < base::win::VERSION_WIN7) |
| 514 return; | 485 return; |
| 515 | 486 |
| 516 // This needs to happen eventually (e.g. so that the appid is fixed and the | 487 // This needs to happen eventually (e.g. so that the appid is fixed and the |
| 517 // run-time Chrome icon is merged with the taskbar shortcut), but this is not | 488 // run-time Chrome icon is merged with the taskbar shortcut), but this is not |
| 518 // urgent and shouldn't delay Chrome startup. | 489 // urgent and shouldn't delay Chrome startup. |
| 519 static const int64_t kMigrateChromiumShortcutsDelaySeconds = 15; | 490 static const int64_t kMigrateTaskbarPinsDelaySeconds = 15; |
| 520 BrowserThread::PostDelayedTask( | 491 BrowserThread::PostDelayedTask( |
| 521 BrowserThread::FILE, FROM_HERE, | 492 BrowserThread::FILE, FROM_HERE, |
| 522 base::Bind(&MigrateChromiumShortcutsCallback), | 493 base::Bind(&MigrateTaskbarPinsCallback), |
| 523 base::TimeDelta::FromSeconds(kMigrateChromiumShortcutsDelaySeconds)); | 494 base::TimeDelta::FromSeconds(kMigrateTaskbarPinsDelaySeconds)); |
| 524 } | 495 } |
| 525 | 496 |
| 526 int ShellIntegration::MigrateShortcutsInPathInternal( | 497 int ShellIntegration::MigrateShortcutsInPathInternal( |
| 527 const base::FilePath& chrome_exe, | 498 const base::FilePath& chrome_exe, |
| 528 const base::FilePath& path, | 499 const base::FilePath& path) { |
| 529 bool clear_dual_mode) { | |
| 530 DCHECK(base::win::GetVersion() >= base::win::VERSION_WIN7); | 500 DCHECK(base::win::GetVersion() >= base::win::VERSION_WIN7); |
| 531 | 501 |
| 532 // Enumerate all pinned shortcuts in the given path directly. | 502 // Enumerate all pinned shortcuts in the given path directly. |
| 533 base::FileEnumerator shortcuts_enum( | 503 base::FileEnumerator shortcuts_enum( |
| 534 path, false, // not recursive | 504 path, false, // not recursive |
| 535 base::FileEnumerator::FILES, FILE_PATH_LITERAL("*.lnk")); | 505 base::FileEnumerator::FILES, FILE_PATH_LITERAL("*.lnk")); |
| 536 | 506 |
| 537 bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_exe); | 507 bool is_per_user_install = InstallUtil::IsPerUserInstall(chrome_exe); |
| 538 | 508 |
| 539 int shortcuts_migrated = 0; | 509 int shortcuts_migrated = 0; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 case VT_LPWSTR: | 562 case VT_LPWSTR: |
| 593 if (expected_app_id != base::string16(propvariant.get().pwszVal)) | 563 if (expected_app_id != base::string16(propvariant.get().pwszVal)) |
| 594 updated_properties.set_app_id(expected_app_id); | 564 updated_properties.set_app_id(expected_app_id); |
| 595 break; | 565 break; |
| 596 default: | 566 default: |
| 597 NOTREACHED(); | 567 NOTREACHED(); |
| 598 continue; | 568 continue; |
| 599 } | 569 } |
| 600 } | 570 } |
| 601 | 571 |
| 602 // Clear |dual_mode| property from any shortcuts that previously had it (as | 572 // Clear dual_mode property from any shortcuts that previously had it (it |
| 603 // requested by caller). | 573 // was only ever installed on shortcuts with the |
| 574 // |default_chromium_model_id|). |
| 604 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); | 575 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); |
| 605 base::string16 default_chromium_model_id( | 576 base::string16 default_chromium_model_id( |
| 606 ShellUtil::GetBrowserModelId(dist, is_per_user_install)); | 577 ShellUtil::GetBrowserModelId(dist, is_per_user_install)); |
| 607 if (clear_dual_mode && expected_app_id == default_chromium_model_id) { | 578 if (expected_app_id == default_chromium_model_id) { |
| 608 propvariant.Reset(); | 579 propvariant.Reset(); |
| 609 if (property_store->GetValue(PKEY_AppUserModel_IsDualMode, | 580 if (property_store->GetValue(PKEY_AppUserModel_IsDualMode, |
| 610 propvariant.Receive()) != S_OK) { | 581 propvariant.Receive()) != S_OK) { |
| 611 // When in doubt, prefer to not update the shortcut. | 582 // When in doubt, prefer to not update the shortcut. |
| 612 NOTREACHED(); | 583 NOTREACHED(); |
| 613 continue; | 584 continue; |
| 614 } | 585 } |
| 615 if (propvariant.get().vt == VT_BOOL && | 586 if (propvariant.get().vt == VT_BOOL && |
| 616 !!propvariant.get().boolVal) { | 587 !!propvariant.get().boolVal) { |
| 617 updated_properties.set_dual_mode(false); | 588 updated_properties.set_dual_mode(false); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 if (!RegisterBrowser()) | 698 if (!RegisterBrowser()) |
| 728 return false; | 699 return false; |
| 729 | 700 |
| 730 if (ShouldResetDefaultBrowser()) | 701 if (ShouldResetDefaultBrowser()) |
| 731 ResetDefaultBrowser(); | 702 ResetDefaultBrowser(); |
| 732 | 703 |
| 733 base::CommandLine cmdline(base::FilePath(L"openwith.exe")); | 704 base::CommandLine cmdline(base::FilePath(L"openwith.exe")); |
| 734 cmdline.AppendArgNative(StartupBrowserCreator::GetDefaultBrowserUrl()); | 705 cmdline.AppendArgNative(StartupBrowserCreator::GetDefaultBrowserUrl()); |
| 735 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid(); | 706 return base::LaunchProcess(cmdline, base::LaunchOptions()).IsValid(); |
| 736 } | 707 } |
| OLD | NEW |