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 // This file defines functions that integrate Chrome in Windows shell. These | 5 // This file defines functions that integrate Chrome in Windows shell. These |
6 // functions can be used by Chrome as well as Chrome installer. All of the | 6 // functions can be used by Chrome as well as Chrome installer. All of the |
7 // work is done by the local functions defined in anonymous namespace in | 7 // work is done by the local functions defined in anonymous namespace in |
8 // this class. | 8 // this class. |
9 | 9 |
10 #include "chrome/installer/util/shell_util.h" | 10 #include "chrome/installer/util/shell_util.h" |
11 | 11 |
12 #include <windows.h> | 12 #include <windows.h> |
13 #include <shlobj.h> | 13 #include <shlobj.h> |
14 #include <shobjidl.h> | 14 #include <shobjidl.h> |
15 | 15 |
16 #include <limits> | 16 #include <limits> |
17 #include <string> | 17 #include <string> |
18 | 18 |
19 #include "base/bind.h" | 19 #include "base/bind.h" |
20 #include "base/command_line.h" | 20 #include "base/command_line.h" |
21 #include "base/files/file_enumerator.h" | 21 #include "base/files/file_enumerator.h" |
22 #include "base/files/file_path.h" | 22 #include "base/files/file_path.h" |
23 #include "base/files/file_util.h" | 23 #include "base/files/file_util.h" |
24 #include "base/lazy_instance.h" | 24 #include "base/lazy_instance.h" |
25 #include "base/logging.h" | 25 #include "base/logging.h" |
| 26 #include "base/macros.h" |
26 #include "base/md5.h" | 27 #include "base/md5.h" |
27 #include "base/memory/scoped_ptr.h" | 28 #include "base/memory/scoped_ptr.h" |
28 #include "base/memory/scoped_vector.h" | 29 #include "base/memory/scoped_vector.h" |
29 #include "base/path_service.h" | 30 #include "base/path_service.h" |
30 #include "base/strings/string16.h" | 31 #include "base/strings/string16.h" |
31 #include "base/strings/string_number_conversions.h" | 32 #include "base/strings/string_number_conversions.h" |
32 #include "base/strings/string_split.h" | 33 #include "base/strings/string_split.h" |
33 #include "base/strings/string_util.h" | 34 #include "base/strings/string_util.h" |
34 #include "base/strings/stringprintf.h" | 35 #include "base/strings/stringprintf.h" |
35 #include "base/strings/utf_string_conversions.h" | 36 #include "base/strings/utf_string_conversions.h" |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 // start->Internet shortcut. | 612 // start->Internet shortcut. |
612 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); | 613 base::string16 start_menu(ShellUtil::kRegStartMenuInternet); |
613 base::string16 app_name = dist->GetBaseAppName() + suffix; | 614 base::string16 app_name = dist->GetBaseAppName() + suffix; |
614 entries->push_back(new RegistryEntry(start_menu, app_name)); | 615 entries->push_back(new RegistryEntry(start_menu, app_name)); |
615 } | 616 } |
616 | 617 |
617 // Checks that all |entries| are present on this computer (or absent if their | 618 // Checks that all |entries| are present on this computer (or absent if their |
618 // |removal_flag_| is set). |look_for_in| is passed to | 619 // |removal_flag_| is set). |look_for_in| is passed to |
619 // RegistryEntry::ExistsInRegistry(). Documentation for it can be found there. | 620 // RegistryEntry::ExistsInRegistry(). Documentation for it can be found there. |
620 bool AreEntriesAsDesired(const ScopedVector<RegistryEntry>& entries, | 621 bool AreEntriesAsDesired(const ScopedVector<RegistryEntry>& entries, |
621 uint32 look_for_in) { | 622 uint32_t look_for_in) { |
622 for (const auto* entry : entries) { | 623 for (const auto* entry : entries) { |
623 if (entry->ExistsInRegistry(look_for_in) != !entry->IsFlaggedForRemoval()) | 624 if (entry->ExistsInRegistry(look_for_in) != !entry->IsFlaggedForRemoval()) |
624 return false; | 625 return false; |
625 } | 626 } |
626 return true; | 627 return true; |
627 } | 628 } |
628 | 629 |
629 // Checks that all required registry entries for Chrome are already present on | 630 // Checks that all required registry entries for Chrome are already present on |
630 // this computer (or absent if their |removal_flag_| is set). | 631 // this computer (or absent if their |removal_flag_| is set). |
631 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 632 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
632 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU | 633 // Note: between r133333 and r154145 we were registering parts of Chrome in HKCU |
633 // and parts in HKLM for user-level installs; we now always register everything | 634 // and parts in HKLM for user-level installs; we now always register everything |
634 // under a single registry root. Not doing so caused http://crbug.com/144910 for | 635 // under a single registry root. Not doing so caused http://crbug.com/144910 for |
635 // users who first-installed Chrome in that revision range (those users are | 636 // users who first-installed Chrome in that revision range (those users are |
636 // still impacted by http://crbug.com/144910). This method will keep returning | 637 // still impacted by http://crbug.com/144910). This method will keep returning |
637 // true for affected users (i.e. who have all the registrations, but over both | 638 // true for affected users (i.e. who have all the registrations, but over both |
638 // registry roots). | 639 // registry roots). |
639 bool IsChromeRegistered(BrowserDistribution* dist, | 640 bool IsChromeRegistered(BrowserDistribution* dist, |
640 const base::FilePath& chrome_exe, | 641 const base::FilePath& chrome_exe, |
641 const base::string16& suffix, | 642 const base::string16& suffix, |
642 uint32 look_for_in) { | 643 uint32_t look_for_in) { |
643 ScopedVector<RegistryEntry> entries; | 644 ScopedVector<RegistryEntry> entries; |
644 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); | 645 GetChromeProgIdEntries(dist, chrome_exe, suffix, &entries); |
645 GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); | 646 GetShellIntegrationEntries(dist, chrome_exe, suffix, &entries); |
646 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); | 647 GetChromeAppRegistrationEntries(chrome_exe, suffix, &entries); |
647 return AreEntriesAsDesired(entries, look_for_in); | 648 return AreEntriesAsDesired(entries, look_for_in); |
648 } | 649 } |
649 | 650 |
650 // This method checks if Chrome is already registered on the local machine | 651 // This method checks if Chrome is already registered on the local machine |
651 // for the requested protocol. It just checks the one value required for this. | 652 // for the requested protocol. It just checks the one value required for this. |
652 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. | 653 // See RegistryEntry::ExistsInRegistry for the behavior of |look_for_in|. |
653 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, | 654 bool IsChromeRegisteredForProtocol(BrowserDistribution* dist, |
654 const base::string16& suffix, | 655 const base::string16& suffix, |
655 const base::string16& protocol, | 656 const base::string16& protocol, |
656 uint32 look_for_in) { | 657 uint32_t look_for_in) { |
657 ScopedVector<RegistryEntry> entries; | 658 ScopedVector<RegistryEntry> entries; |
658 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); | 659 GetProtocolCapabilityEntries(dist, suffix, protocol, &entries); |
659 return AreEntriesAsDesired(entries, look_for_in); | 660 return AreEntriesAsDesired(entries, look_for_in); |
660 } | 661 } |
661 | 662 |
662 // This method registers Chrome on Vista by launching an elevated setup.exe. | 663 // This method registers Chrome on Vista by launching an elevated setup.exe. |
663 // That will show the user the standard Vista elevation prompt. If the user | 664 // That will show the user the standard Vista elevation prompt. If the user |
664 // accepts it the new process will make the necessary changes and return SUCCESS | 665 // accepts it the new process will make the necessary changes and return SUCCESS |
665 // that we capture and return. | 666 // that we capture and return. |
666 // If protocol is non-empty we will also register Chrome as being capable of | 667 // If protocol is non-empty we will also register Chrome as being capable of |
(...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2026 | 2027 |
2027 RemoveRunVerbOnWindows8(dist, chrome_exe); | 2028 RemoveRunVerbOnWindows8(dist, chrome_exe); |
2028 | 2029 |
2029 bool user_level = InstallUtil::IsPerUserInstall(chrome_exe); | 2030 bool user_level = InstallUtil::IsPerUserInstall(chrome_exe); |
2030 HKEY root = DetermineRegistrationRoot(user_level); | 2031 HKEY root = DetermineRegistrationRoot(user_level); |
2031 | 2032 |
2032 // Look only in HKLM for system-level installs (otherwise, if a user-level | 2033 // Look only in HKLM for system-level installs (otherwise, if a user-level |
2033 // install is also present, it will lead IsChromeRegistered() to think this | 2034 // install is also present, it will lead IsChromeRegistered() to think this |
2034 // system-level install isn't registered properly as it is shadowed by the | 2035 // system-level install isn't registered properly as it is shadowed by the |
2035 // user-level install's registrations). | 2036 // user-level install's registrations). |
2036 uint32 look_for_in = user_level ? | 2037 uint32_t look_for_in = user_level ? RegistryEntry::LOOK_IN_HKCU_THEN_HKLM |
2037 RegistryEntry::LOOK_IN_HKCU_THEN_HKLM : RegistryEntry::LOOK_IN_HKLM; | 2038 : RegistryEntry::LOOK_IN_HKLM; |
2038 | 2039 |
2039 // Check if chrome is already registered with this suffix. | 2040 // Check if chrome is already registered with this suffix. |
2040 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) | 2041 if (IsChromeRegistered(dist, chrome_exe, suffix, look_for_in)) |
2041 return true; | 2042 return true; |
2042 | 2043 |
2043 bool result = true; | 2044 bool result = true; |
2044 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 2045 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
2045 // Do the full registration if we can do it at user-level or if the user is | 2046 // Do the full registration if we can do it at user-level or if the user is |
2046 // an admin. | 2047 // an admin. |
2047 ScopedVector<RegistryEntry> progid_and_appreg_entries; | 2048 ScopedVector<RegistryEntry> progid_and_appreg_entries; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2108 return false; | 2109 return false; |
2109 } | 2110 } |
2110 | 2111 |
2111 bool user_level = InstallUtil::IsPerUserInstall(chrome_exe); | 2112 bool user_level = InstallUtil::IsPerUserInstall(chrome_exe); |
2112 HKEY root = DetermineRegistrationRoot(user_level); | 2113 HKEY root = DetermineRegistrationRoot(user_level); |
2113 | 2114 |
2114 // Look only in HKLM for system-level installs (otherwise, if a user-level | 2115 // Look only in HKLM for system-level installs (otherwise, if a user-level |
2115 // install is also present, it could lead IsChromeRegisteredForProtocol() to | 2116 // install is also present, it could lead IsChromeRegisteredForProtocol() to |
2116 // think this system-level install isn't registered properly as it may be | 2117 // think this system-level install isn't registered properly as it may be |
2117 // shadowed by the user-level install's registrations). | 2118 // shadowed by the user-level install's registrations). |
2118 uint32 look_for_in = user_level ? | 2119 uint32_t look_for_in = user_level ? RegistryEntry::LOOK_IN_HKCU_THEN_HKLM |
2119 RegistryEntry::LOOK_IN_HKCU_THEN_HKLM : RegistryEntry::LOOK_IN_HKLM; | 2120 : RegistryEntry::LOOK_IN_HKLM; |
2120 | 2121 |
2121 // Check if chrome is already registered with this suffix. | 2122 // Check if chrome is already registered with this suffix. |
2122 if (IsChromeRegisteredForProtocol(dist, suffix, protocol, look_for_in)) | 2123 if (IsChromeRegisteredForProtocol(dist, suffix, protocol, look_for_in)) |
2123 return true; | 2124 return true; |
2124 | 2125 |
2125 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { | 2126 if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { |
2126 // We can do this operation directly. | 2127 // We can do this operation directly. |
2127 // First, make sure Chrome is fully registered on this machine. | 2128 // First, make sure Chrome is fully registered on this machine. |
2128 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) | 2129 if (!RegisterChromeBrowser(dist, chrome_exe, suffix, false)) |
2129 return false; | 2130 return false; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2218 if (::GetUserName(user_name, &size) == 0 || size < 1) { | 2219 if (::GetUserName(user_name, &size) == 0 || size < 1) { |
2219 NOTREACHED(); | 2220 NOTREACHED(); |
2220 return false; | 2221 return false; |
2221 } | 2222 } |
2222 suffix->reserve(size); | 2223 suffix->reserve(size); |
2223 suffix->assign(1, L'.'); | 2224 suffix->assign(1, L'.'); |
2224 suffix->append(user_name, size - 1); | 2225 suffix->append(user_name, size - 1); |
2225 return true; | 2226 return true; |
2226 } | 2227 } |
2227 | 2228 |
2228 base::string16 ShellUtil::ByteArrayToBase32(const uint8* bytes, size_t size) { | 2229 base::string16 ShellUtil::ByteArrayToBase32(const uint8_t* bytes, size_t size) { |
2229 static const char kEncoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; | 2230 static const char kEncoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; |
2230 | 2231 |
2231 // Eliminate special cases first. | 2232 // Eliminate special cases first. |
2232 if (size == 0) { | 2233 if (size == 0) { |
2233 return base::string16(); | 2234 return base::string16(); |
2234 } else if (size == 1) { | 2235 } else if (size == 1) { |
2235 base::string16 ret; | 2236 base::string16 ret; |
2236 ret.push_back(kEncoding[(bytes[0] & 0xf8) >> 3]); | 2237 ret.push_back(kEncoding[(bytes[0] & 0xf8) >> 3]); |
2237 ret.push_back(kEncoding[(bytes[0] & 0x07) << 2]); | 2238 ret.push_back(kEncoding[(bytes[0] & 0x07) << 2]); |
2238 return ret; | 2239 return ret; |
2239 } else if (size >= std::numeric_limits<size_t>::max() / 8) { | 2240 } else if (size >= std::numeric_limits<size_t>::max() / 8) { |
2240 // If |size| is too big, the calculation of |encoded_length| below will | 2241 // If |size| is too big, the calculation of |encoded_length| below will |
2241 // overflow. | 2242 // overflow. |
2242 NOTREACHED(); | 2243 NOTREACHED(); |
2243 return base::string16(); | 2244 return base::string16(); |
2244 } | 2245 } |
2245 | 2246 |
2246 // Overestimate the number of bits in the string by 4 so that dividing by 5 | 2247 // Overestimate the number of bits in the string by 4 so that dividing by 5 |
2247 // is the equivalent of rounding up the actual number of bits divided by 5. | 2248 // is the equivalent of rounding up the actual number of bits divided by 5. |
2248 const size_t encoded_length = (size * 8 + 4) / 5; | 2249 const size_t encoded_length = (size * 8 + 4) / 5; |
2249 | 2250 |
2250 base::string16 ret; | 2251 base::string16 ret; |
2251 ret.reserve(encoded_length); | 2252 ret.reserve(encoded_length); |
2252 | 2253 |
2253 // A bit stream which will be read from the left and appended to from the | 2254 // A bit stream which will be read from the left and appended to from the |
2254 // right as it's emptied. | 2255 // right as it's emptied. |
2255 uint16 bit_stream = (bytes[0] << 8) + bytes[1]; | 2256 uint16_t bit_stream = (bytes[0] << 8) + bytes[1]; |
2256 size_t next_byte_index = 2; | 2257 size_t next_byte_index = 2; |
2257 int free_bits = 0; | 2258 int free_bits = 0; |
2258 while (free_bits < 16) { | 2259 while (free_bits < 16) { |
2259 // Extract the 5 leftmost bits in the stream | 2260 // Extract the 5 leftmost bits in the stream |
2260 ret.push_back(kEncoding[(bit_stream & 0xf800) >> 11]); | 2261 ret.push_back(kEncoding[(bit_stream & 0xf800) >> 11]); |
2261 bit_stream <<= 5; | 2262 bit_stream <<= 5; |
2262 free_bits += 5; | 2263 free_bits += 5; |
2263 | 2264 |
2264 // If there is enough room in the bit stream, inject another byte (if there | 2265 // If there is enough room in the bit stream, inject another byte (if there |
2265 // are any left...). | 2266 // are any left...). |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2336 itr != entries.end(); ++itr) | 2337 itr != entries.end(); ++itr) |
2337 (*itr)->AddToWorkItemList(root, items.get()); | 2338 (*itr)->AddToWorkItemList(root, items.get()); |
2338 | 2339 |
2339 // Apply all the registry changes and if there is a problem, rollback | 2340 // Apply all the registry changes and if there is a problem, rollback |
2340 if (!items->Do()) { | 2341 if (!items->Do()) { |
2341 items->Rollback(); | 2342 items->Rollback(); |
2342 return false; | 2343 return false; |
2343 } | 2344 } |
2344 return true; | 2345 return true; |
2345 } | 2346 } |
OLD | NEW |