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

Side by Side Diff: chrome/install_static/install_util.cc

Issue 2549593002: Revert of Make Crashpad use the user data dir, rather than always default location (Closed)
Patch Set: Created 4 years 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
« no previous file with comments | « chrome/install_static/install_util.h ('k') | chrome/install_static/install_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/install_static/install_util.h" 5 #include "chrome/install_static/install_util.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <assert.h> 8 #include <assert.h>
9 #include <stdlib.h>
10 #include <string.h> 9 #include <string.h>
11 10
12 #include <algorithm> 11 #include <algorithm>
13 #include <memory> 12 #include <memory>
14 #include <sstream> 13 #include <sstream>
15 14
16 #include "chrome/install_static/install_details.h" 15 #include "chrome/install_static/install_details.h"
17 #include "chrome/install_static/install_modes.h" 16 #include "chrome/install_static/install_modes.h"
18 #include "chrome/install_static/policy_path_parser.h"
19 #include "chrome/install_static/user_data_dir.h"
20 #include "chrome_elf/nt_registry/nt_registry.h" 17 #include "chrome_elf/nt_registry/nt_registry.h"
21 18
22 namespace install_static { 19 namespace install_static {
23 20
24 ProcessType g_process_type = ProcessType::UNINITIALIZED; 21 ProcessType g_process_type = ProcessType::UNINITIALIZED;
25 22
26 const wchar_t kRegValueChromeStatsSample[] = L"UsageStatsInSample"; 23 const wchar_t kRegValueChromeStatsSample[] = L"UsageStatsInSample";
27 24
28 // TODO(ananta) 25 // TODO(ananta)
29 // http://crbug.com/604923 26 // http://crbug.com/604923
30 // The constants defined in this file are also defined in chrome/installer and 27 // The constants defined in this file are also defined in chrome/installer and
31 // other places. we need to unify them. 28 // other places. we need to unify them.
32 const wchar_t kHeadless[] = L"CHROME_HEADLESS"; 29 const wchar_t kHeadless[] = L"CHROME_HEADLESS";
33 const wchar_t kShowRestart[] = L"CHROME_CRASHED"; 30 const wchar_t kShowRestart[] = L"CHROME_CRASHED";
34 const wchar_t kRestartInfo[] = L"CHROME_RESTART"; 31 const wchar_t kRestartInfo[] = L"CHROME_RESTART";
35 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT"; 32 const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT";
36 33
37 const wchar_t kCrashpadHandler[] = L"crashpad-handler"; 34 const char kGpuProcess[] = "gpu-process";
38 const wchar_t kProcessType[] = L"type"; 35 const char kPpapiPluginProcess[] = "ppapi";
39 const wchar_t kUserDataDirSwitch[] = L"user-data-dir"; 36 const char kRendererProcess[] = "renderer";
40 const wchar_t kUtilityProcess[] = L"utility"; 37 const char kUtilityProcess[] = "utility";
38 const char kProcessType[] = "type";
39 const char kCrashpadHandler[] = "crashpad-handler";
41 40
42 namespace { 41 namespace {
43 42
44 // TODO(ananta) 43 // TODO(ananta)
45 // http://crbug.com/604923 44 // http://crbug.com/604923
46 // The constants defined in this file are also defined in chrome/installer and 45 // The constants defined in this file are also defined in chrome/installer and
47 // other places. we need to unify them. 46 // other places. we need to unify them.
48 // Chrome channel display names. 47 // Chrome channel display names.
49 constexpr wchar_t kChromeChannelDev[] = L"dev"; 48 constexpr wchar_t kChromeChannelDev[] = L"dev";
50 constexpr wchar_t kChromeChannelBeta[] = L"beta"; 49 constexpr wchar_t kChromeChannelBeta[] = L"beta";
51 constexpr wchar_t kChromeChannelStableExplicit[] = L"stable"; 50 constexpr wchar_t kChromeChannelStableExplicit[] = L"stable";
52 51
53 // TODO(ananta) 52 // TODO(ananta)
54 // http://crbug.com/604923 53 // http://crbug.com/604923
55 // These constants are defined in the chrome/installer directory as well. We 54 // These constants are defined in the chrome/installer directory as well. We
56 // need to unify them. 55 // need to unify them.
57 constexpr wchar_t kRegValueAp[] = L"ap"; 56 constexpr wchar_t kRegValueAp[] = L"ap";
58 constexpr wchar_t kRegValueUsageStats[] = L"usagestats"; 57 constexpr wchar_t kRegValueUsageStats[] = L"usagestats";
59 constexpr wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled"; 58 constexpr wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled";
60 59
60 constexpr wchar_t kUserDataDirname[] = L"User Data";
61 constexpr wchar_t kBrowserCrashDumpMetricsSubKey[] = 61 constexpr wchar_t kBrowserCrashDumpMetricsSubKey[] =
62 L"\\BrowserCrashDumpAttempts"; 62 L"\\BrowserCrashDumpAttempts";
63 63
64 void Trace(const wchar_t* format_string, ...) { 64 void Trace(const wchar_t* format_string, ...) {
65 static const int kMaxLogBufferSize = 1024; 65 static const int kMaxLogBufferSize = 1024;
66 static wchar_t buffer[kMaxLogBufferSize] = {}; 66 static wchar_t buffer[kMaxLogBufferSize] = {};
67 67
68 va_list args = {}; 68 va_list args = {};
69 69
70 va_start(args, format_string); 70 va_start(args, format_string);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 uint32_t size = 0; 144 uint32_t size = 0;
145 BOOL r = ::VerQueryValueW(version_resource, sub_block, &value, &size); 145 BOOL r = ::VerQueryValueW(version_resource, sub_block, &value, &size);
146 if (r && value) { 146 if (r && value) {
147 value_str->assign(static_cast<wchar_t*>(value)); 147 value_str->assign(static_cast<wchar_t*>(value));
148 return true; 148 return true;
149 } 149 }
150 } 150 }
151 return false; 151 return false;
152 } 152 }
153 153
154 bool DirectoryExists(const std::wstring& path) { 154 bool RecursiveDirectoryCreate(const std::wstring& full_path) {
155 DWORD file_attributes = ::GetFileAttributes(path.c_str()); 155 // If the path exists, we've succeeded if it's a directory, failed otherwise.
156 if (file_attributes == INVALID_FILE_ATTRIBUTES) 156 const wchar_t* full_path_str = full_path.c_str();
157 DWORD file_attributes = ::GetFileAttributes(full_path_str);
158 if (file_attributes != INVALID_FILE_ATTRIBUTES) {
159 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
160 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str);
161 return true;
162 }
163 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__,
164 full_path_str);
157 return false; 165 return false;
158 return (file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; 166 }
167
168 // Invariant: Path does not exist as file or directory.
169
170 // Attempt to create the parent recursively. This will immediately return
171 // true if it already exists, otherwise will create all required parent
172 // directories starting with the highest-level missing parent.
173 std::wstring parent_path;
174 std::size_t pos = full_path.find_last_of(L"/\\");
175 if (pos != std::wstring::npos) {
176 parent_path = full_path.substr(0, pos);
177 if (!RecursiveDirectoryCreate(parent_path)) {
178 Trace(L"Failed to create one of the parent directories");
179 return false;
180 }
181 }
182 if (!::CreateDirectory(full_path_str, nullptr)) {
183 DWORD error_code = ::GetLastError();
184 if (error_code == ERROR_ALREADY_EXISTS) {
185 DWORD file_attributes = ::GetFileAttributes(full_path_str);
186 if ((file_attributes != INVALID_FILE_ATTRIBUTES) &&
187 ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) {
188 // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we
189 // were racing with someone creating the same directory, or a file
190 // with the same path. If the directory exists, we lost the
191 // race to create the same directory.
192 return true;
193 } else {
194 Trace(L"Failed to create directory %ls, last error is %d\n",
195 full_path_str, error_code);
196 return false;
197 }
198 }
199 }
200 return true;
201 }
202
203 // Appends "[kCompanyPathName\]kProductPathName[install_suffix]" to |path|,
204 // returning a reference to |path|.
205 std::wstring& AppendChromeInstallSubDirectory(std::wstring* path,
206 bool include_suffix) {
207 if (*kCompanyPathName) {
208 path->append(kCompanyPathName);
209 path->push_back(L'\\');
210 }
211 path->append(kProductPathName, kProductPathNameLength);
212 if (!include_suffix)
213 return *path;
214 return path->append(InstallDetails::Get().install_suffix());
159 } 215 }
160 216
161 std::wstring GetChromeInstallRegistryPath() { 217 std::wstring GetChromeInstallRegistryPath() {
162 std::wstring registry_path = L"Software\\"; 218 std::wstring registry_path = L"Software\\";
163 return AppendChromeInstallSubDirectory( 219 return AppendChromeInstallSubDirectory(&registry_path,
164 InstallDetails::Get().mode(), true /* include_suffix */, &registry_path); 220 true /* include_suffix */);
165 } 221 }
166 222
167 // Returns true if the |source| string matches the |pattern|. The pattern 223 // Returns true if the |source| string matches the |pattern|. The pattern
168 // may contain wildcards like '?' which matches one character or a '*' 224 // may contain wildcards like '?' which matches one character or a '*'
169 // which matches 0 or more characters. 225 // which matches 0 or more characters.
170 // Please note that pattern matches the whole string. If you want to find 226 // Please note that pattern matches the whole string. If you want to find
171 // something in the middle of the string then you need to specify the pattern 227 // something in the middle of the string then you need to specify the pattern
172 // as '*xyz*'. 228 // as '*xyz*'.
173 // |source_index| is the index of the current character being matched in 229 // |source_index| is the index of the current character being matched in
174 // |source|. 230 // |source|.
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 KEY_SET_VALUE | KEY_WOW64_32KEY, &key_handle)) { 417 KEY_SET_VALUE | KEY_WOW64_32KEY, &key_handle)) {
362 return false; 418 return false;
363 } 419 }
364 420
365 bool success = nt::SetRegValueDWORD(key_handle, kRegValueChromeStatsSample, 421 bool success = nt::SetRegValueDWORD(key_handle, kRegValueChromeStatsSample,
366 in_sample ? 1 : 0); 422 in_sample ? 1 : 0);
367 nt::CloseRegKey(key_handle); 423 nt::CloseRegKey(key_handle);
368 return success; 424 return success;
369 } 425 }
370 426
371 // Appends "[kCompanyPathName\]kProductPathName[install_suffix]" to |path|,
372 // returning a reference to |path|.
373 std::wstring& AppendChromeInstallSubDirectory(const InstallConstants& mode,
374 bool include_suffix,
375 std::wstring* path) {
376 if (*kCompanyPathName) {
377 path->append(kCompanyPathName);
378 path->push_back(L'\\');
379 }
380 path->append(kProductPathName, kProductPathNameLength);
381 if (!include_suffix)
382 return *path;
383 return path->append(mode.install_suffix);
384 }
385
386 bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) { 427 bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) {
387 std::wstring policies_path = L"SOFTWARE\\Policies\\"; 428 std::wstring policies_path = L"SOFTWARE\\Policies\\";
388 AppendChromeInstallSubDirectory(InstallDetails::Get().mode(), 429 AppendChromeInstallSubDirectory(&policies_path, false /* !include_suffix */);
389 false /* !include_suffix */, &policies_path);
390 DWORD value = 0; 430 DWORD value = 0;
391 431
392 // First, try HKLM. 432 // First, try HKLM.
393 if (nt::QueryRegValueDWORD(nt::HKLM, nt::NONE, policies_path.c_str(), 433 if (nt::QueryRegValueDWORD(nt::HKLM, nt::NONE, policies_path.c_str(),
394 kMetricsReportingEnabled, &value)) { 434 kMetricsReportingEnabled, &value)) {
395 *crash_reporting_enabled = (value != 0); 435 *crash_reporting_enabled = (value != 0);
396 return true; 436 return true;
397 } 437 }
398 438
399 // Second, try HKCU. 439 // Second, try HKCU.
(...skipping 26 matching lines...) Expand all
426 } 466 }
427 467
428 g_process_type = ProcessType::BROWSER_PROCESS; 468 g_process_type = ProcessType::BROWSER_PROCESS;
429 } 469 }
430 470
431 bool IsNonBrowserProcess() { 471 bool IsNonBrowserProcess() {
432 assert(g_process_type != ProcessType::UNINITIALIZED); 472 assert(g_process_type != ProcessType::UNINITIALIZED);
433 return g_process_type == ProcessType::NON_BROWSER_PROCESS; 473 return g_process_type == ProcessType::NON_BROWSER_PROCESS;
434 } 474 }
435 475
436 std::wstring GetCrashDumpLocation() { 476 bool GetDefaultUserDataDirectory(std::wstring* result) {
437 // In order to be able to start crash handling very early and in chrome_elf, 477 // This environment variable should be set on Windows Vista and later
438 // we cannot rely on chrome's PathService entries (for DIR_CRASH_DUMPS) being 478 // (https://msdn.microsoft.com/library/windows/desktop/dd378457.aspx).
439 // available on Windows. See https://crbug.com/564398. 479 std::wstring user_data_dir = GetEnvironmentString16(L"LOCALAPPDATA");
440 std::wstring user_data_dir; 480
441 bool ret = GetUserDataDirectory(&user_data_dir, nullptr); 481 if (user_data_dir.empty()) {
442 assert(ret); 482 // LOCALAPPDATA was not set; fallback to the temporary files path.
443 IgnoreUnused(ret); 483 DWORD size = ::GetTempPath(0, nullptr);
444 return user_data_dir.append(L"\\Crashpad"); 484 if (!size)
485 return false;
486 user_data_dir.resize(size + 1);
487 size = ::GetTempPath(size + 1, &user_data_dir[0]);
488 if (!size || size >= user_data_dir.size())
489 return false;
490 user_data_dir.resize(size);
491 }
492
493 result->swap(user_data_dir);
494 if ((*result)[result->length() - 1] != L'\\')
495 result->push_back(L'\\');
496 AppendChromeInstallSubDirectory(result, true /* include_suffix */);
497 result->push_back(L'\\');
498 result->append(kUserDataDirname);
499 return true;
500 }
501
502 bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) {
503 // In order to be able to start crash handling very early, we do not rely on
504 // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on
505 // Windows. See https://crbug.com/564398.
506 if (!GetDefaultUserDataDirectory(crash_dir))
507 return false;
508
509 // We have to make sure the user data dir exists on first run. See
510 // http://crbug.com/591504.
511 if (!RecursiveDirectoryCreate(*crash_dir))
512 return false;
513 crash_dir->append(L"\\Crashpad");
514 return true;
445 } 515 }
446 516
447 std::string GetEnvironmentString(const std::string& variable_name) { 517 std::string GetEnvironmentString(const std::string& variable_name) {
448 return UTF16ToUTF8( 518 return UTF16ToUTF8(
449 GetEnvironmentString16(UTF8ToUTF16(variable_name).c_str())); 519 GetEnvironmentString16(UTF8ToUTF16(variable_name).c_str()));
450 } 520 }
451 521
452 std::wstring GetEnvironmentString16(const wchar_t* variable_name) { 522 std::wstring GetEnvironmentString16(const wchar_t* variable_name) {
453 DWORD value_length = ::GetEnvironmentVariableW(variable_name, nullptr, 0); 523 DWORD value_length = ::GetEnvironmentVariableW(variable_name, nullptr, 0);
454 if (!value_length) 524 if (!value_length)
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 bool trim_spaces) { 644 bool trim_spaces) {
575 return TokenizeStringT<std::string>(str, delimiter, trim_spaces); 645 return TokenizeStringT<std::string>(str, delimiter, trim_spaces);
576 } 646 }
577 647
578 std::vector<std::wstring> TokenizeString16(const std::wstring& str, 648 std::vector<std::wstring> TokenizeString16(const std::wstring& str,
579 wchar_t delimiter, 649 wchar_t delimiter,
580 bool trim_spaces) { 650 bool trim_spaces) {
581 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces); 651 return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces);
582 } 652 }
583 653
584 std::wstring GetSwitchValueFromCommandLine(const std::wstring& command_line, 654 std::string GetSwitchValueFromCommandLine(const std::string& command_line,
585 const std::wstring& switch_name) { 655 const std::string& switch_name) {
586 assert(!command_line.empty()); 656 assert(!command_line.empty());
587 assert(!switch_name.empty()); 657 assert(!switch_name.empty());
588 658
589 std::wstring command_line_copy = command_line; 659 std::string command_line_copy = command_line;
590 // Remove leading and trailing spaces. 660 // Remove leading and trailing spaces.
591 TrimT<std::wstring>(&command_line_copy); 661 TrimT<std::string>(&command_line_copy);
592 662
593 // Find the switch in the command line. If we don't find the switch, return 663 // Find the switch in the command line. If we don't find the switch, return
594 // an empty string. 664 // an empty string.
595 std::wstring switch_token = L"--"; 665 std::string switch_token = "--";
596 switch_token += switch_name; 666 switch_token += switch_name;
597 switch_token += L"="; 667 switch_token += "=";
598 size_t switch_offset = command_line_copy.find(switch_token); 668 size_t switch_offset = command_line_copy.find(switch_token);
599 if (switch_offset == std::string::npos) 669 if (switch_offset == std::string::npos)
600 return std::wstring(); 670 return std::string();
601 671
602 // The format is "--<switch name>=blah". Look for a space after the 672 // The format is "--<switch name>=blah". Look for a space after the
603 // "--<switch name>=" string. If we don't find a space assume that the switch 673 // "--<switch name>=" string. If we don't find a space assume that the switch
604 // value ends at the end of the command line. 674 // value ends at the end of the command line.
605 size_t switch_value_start_offset = switch_offset + switch_token.length(); 675 size_t switch_value_start_offset = switch_offset + switch_token.length();
606 if (std::wstring(kWhiteSpaces16).find( 676 if (std::string(kWhiteSpaces).find(
607 command_line_copy[switch_value_start_offset]) != std::wstring::npos) { 677 command_line_copy[switch_value_start_offset]) != std::string::npos) {
608 switch_value_start_offset = command_line_copy.find_first_not_of( 678 switch_value_start_offset = command_line_copy.find_first_not_of(
609 GetWhiteSpacesForType<std::wstring>(), switch_value_start_offset); 679 GetWhiteSpacesForType<std::string>(), switch_value_start_offset);
610 if (switch_value_start_offset == std::wstring::npos) 680 if (switch_value_start_offset == std::string::npos)
611 return std::wstring(); 681 return std::string();
612 } 682 }
613 size_t switch_value_end_offset = 683 size_t switch_value_end_offset =
614 command_line_copy.find_first_of(GetWhiteSpacesForType<std::wstring>(), 684 command_line_copy.find_first_of(GetWhiteSpacesForType<std::string>(),
615 switch_value_start_offset); 685 switch_value_start_offset);
616 if (switch_value_end_offset == std::wstring::npos) 686 if (switch_value_end_offset == std::string::npos)
617 switch_value_end_offset = command_line_copy.length(); 687 switch_value_end_offset = command_line_copy.length();
618 688
619 std::wstring switch_value = command_line_copy.substr( 689 std::string switch_value = command_line_copy.substr(
620 switch_value_start_offset, 690 switch_value_start_offset,
621 switch_value_end_offset - (switch_offset + switch_token.length())); 691 switch_value_end_offset - (switch_offset + switch_token.length()));
622 TrimT<std::wstring>(&switch_value); 692 TrimT<std::string>(&switch_value);
623 return switch_value; 693 return switch_value;
624 } 694 }
625 695
626 bool RecursiveDirectoryCreate(const std::wstring& full_path) {
627 // If the path exists, we've succeeded if it's a directory, failed otherwise.
628 const wchar_t* full_path_str = full_path.c_str();
629 DWORD file_attributes = ::GetFileAttributes(full_path_str);
630 if (file_attributes != INVALID_FILE_ATTRIBUTES) {
631 if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
632 Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str);
633 return true;
634 }
635 Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__,
636 full_path_str);
637 return false;
638 }
639
640 // Invariant: Path does not exist as file or directory.
641
642 // Attempt to create the parent recursively. This will immediately return
643 // true if it already exists, otherwise will create all required parent
644 // directories starting with the highest-level missing parent.
645 std::wstring parent_path;
646 std::size_t pos = full_path.find_last_of(L"/\\");
647 if (pos != std::wstring::npos) {
648 parent_path = full_path.substr(0, pos);
649 if (!RecursiveDirectoryCreate(parent_path)) {
650 Trace(L"Failed to create one of the parent directories");
651 return false;
652 }
653 }
654 if (!::CreateDirectory(full_path_str, nullptr)) {
655 DWORD error_code = ::GetLastError();
656 if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path_str)) {
657 // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we
658 // were racing with someone creating the same directory, or a file
659 // with the same path. If the directory exists, we lost the
660 // race to create the same directory.
661 return true;
662 } else {
663 Trace(L"Failed to create directory %ls, last error is %d\n",
664 full_path_str, error_code);
665 return false;
666 }
667 }
668 return true;
669 }
670
671 // This function takes these inputs rather than accessing the module's 696 // This function takes these inputs rather than accessing the module's
672 // InstallDetails instance since it is used to bootstrap InstallDetails. 697 // InstallDetails instance since it is used to bootstrap InstallDetails.
673 std::wstring DetermineChannel(const InstallConstants& mode, 698 std::wstring DetermineChannel(const InstallConstants& mode,
674 bool system_level, 699 bool system_level,
675 bool multi_install) { 700 bool multi_install) {
676 if (!kUseGoogleUpdateIntegration) 701 if (!kUseGoogleUpdateIntegration)
677 return std::wstring(); 702 return std::wstring();
678 703
679 switch (mode.channel_strategy) { 704 switch (mode.channel_strategy) {
680 case ChannelStrategy::UNSUPPORTED: 705 case ChannelStrategy::UNSUPPORTED:
681 assert(false); 706 assert(false);
682 break; 707 break;
683 case ChannelStrategy::ADDITIONAL_PARAMETERS: 708 case ChannelStrategy::ADDITIONAL_PARAMETERS:
684 return ChannelFromAdditionalParameters(mode, system_level, multi_install); 709 return ChannelFromAdditionalParameters(mode, system_level, multi_install);
685 case ChannelStrategy::FIXED: 710 case ChannelStrategy::FIXED:
686 return mode.default_channel_name; 711 return mode.default_channel_name;
687 } 712 }
688 713
689 return std::wstring(); 714 return std::wstring();
690 } 715 }
691 716
692 } // namespace install_static 717 } // namespace install_static
OLDNEW
« no previous file with comments | « chrome/install_static/install_util.h ('k') | chrome/install_static/install_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698