Index: chrome/install_static/install_util.cc |
diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc |
index fcbcb4ffbd6e2100d93ba307234147bd61e1ca38..edec76d2e567b011248c619f0f601cedeb09bc7a 100644 |
--- a/chrome/install_static/install_util.cc |
+++ b/chrome/install_static/install_util.cc |
@@ -6,7 +6,6 @@ |
#include <windows.h> |
#include <assert.h> |
-#include <stdlib.h> |
#include <string.h> |
#include <algorithm> |
@@ -15,8 +14,6 @@ |
#include "chrome/install_static/install_details.h" |
#include "chrome/install_static/install_modes.h" |
-#include "chrome/install_static/policy_path_parser.h" |
-#include "chrome/install_static/user_data_dir.h" |
#include "chrome_elf/nt_registry/nt_registry.h" |
namespace install_static { |
@@ -34,10 +31,12 @@ |
const wchar_t kRestartInfo[] = L"CHROME_RESTART"; |
const wchar_t kRtlLocale[] = L"RIGHT_TO_LEFT"; |
-const wchar_t kCrashpadHandler[] = L"crashpad-handler"; |
-const wchar_t kProcessType[] = L"type"; |
-const wchar_t kUserDataDirSwitch[] = L"user-data-dir"; |
-const wchar_t kUtilityProcess[] = L"utility"; |
+const char kGpuProcess[] = "gpu-process"; |
+const char kPpapiPluginProcess[] = "ppapi"; |
+const char kRendererProcess[] = "renderer"; |
+const char kUtilityProcess[] = "utility"; |
+const char kProcessType[] = "type"; |
+const char kCrashpadHandler[] = "crashpad-handler"; |
namespace { |
@@ -58,6 +57,7 @@ |
constexpr wchar_t kRegValueUsageStats[] = L"usagestats"; |
constexpr wchar_t kMetricsReportingEnabled[] = L"MetricsReportingEnabled"; |
+constexpr wchar_t kUserDataDirname[] = L"User Data"; |
constexpr wchar_t kBrowserCrashDumpMetricsSubKey[] = |
L"\\BrowserCrashDumpAttempts"; |
@@ -151,17 +151,73 @@ |
return false; |
} |
-bool DirectoryExists(const std::wstring& path) { |
- DWORD file_attributes = ::GetFileAttributes(path.c_str()); |
- if (file_attributes == INVALID_FILE_ATTRIBUTES) |
- return false; |
- return (file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; |
+bool RecursiveDirectoryCreate(const std::wstring& full_path) { |
+ // If the path exists, we've succeeded if it's a directory, failed otherwise. |
+ const wchar_t* full_path_str = full_path.c_str(); |
+ DWORD file_attributes = ::GetFileAttributes(full_path_str); |
+ if (file_attributes != INVALID_FILE_ATTRIBUTES) { |
+ if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
+ Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str); |
+ return true; |
+ } |
+ Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__, |
+ full_path_str); |
+ return false; |
+ } |
+ |
+ // Invariant: Path does not exist as file or directory. |
+ |
+ // Attempt to create the parent recursively. This will immediately return |
+ // true if it already exists, otherwise will create all required parent |
+ // directories starting with the highest-level missing parent. |
+ std::wstring parent_path; |
+ std::size_t pos = full_path.find_last_of(L"/\\"); |
+ if (pos != std::wstring::npos) { |
+ parent_path = full_path.substr(0, pos); |
+ if (!RecursiveDirectoryCreate(parent_path)) { |
+ Trace(L"Failed to create one of the parent directories"); |
+ return false; |
+ } |
+ } |
+ if (!::CreateDirectory(full_path_str, nullptr)) { |
+ DWORD error_code = ::GetLastError(); |
+ if (error_code == ERROR_ALREADY_EXISTS) { |
+ DWORD file_attributes = ::GetFileAttributes(full_path_str); |
+ if ((file_attributes != INVALID_FILE_ATTRIBUTES) && |
+ ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)) { |
+ // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we |
+ // were racing with someone creating the same directory, or a file |
+ // with the same path. If the directory exists, we lost the |
+ // race to create the same directory. |
+ return true; |
+ } else { |
+ Trace(L"Failed to create directory %ls, last error is %d\n", |
+ full_path_str, error_code); |
+ return false; |
+ } |
+ } |
+ } |
+ return true; |
+} |
+ |
+// Appends "[kCompanyPathName\]kProductPathName[install_suffix]" to |path|, |
+// returning a reference to |path|. |
+std::wstring& AppendChromeInstallSubDirectory(std::wstring* path, |
+ bool include_suffix) { |
+ if (*kCompanyPathName) { |
+ path->append(kCompanyPathName); |
+ path->push_back(L'\\'); |
+ } |
+ path->append(kProductPathName, kProductPathNameLength); |
+ if (!include_suffix) |
+ return *path; |
+ return path->append(InstallDetails::Get().install_suffix()); |
} |
std::wstring GetChromeInstallRegistryPath() { |
std::wstring registry_path = L"Software\\"; |
- return AppendChromeInstallSubDirectory( |
- InstallDetails::Get().mode(), true /* include_suffix */, ®istry_path); |
+ return AppendChromeInstallSubDirectory(®istry_path, |
+ true /* include_suffix */); |
} |
// Returns true if the |source| string matches the |pattern|. The pattern |
@@ -368,25 +424,9 @@ |
return success; |
} |
-// Appends "[kCompanyPathName\]kProductPathName[install_suffix]" to |path|, |
-// returning a reference to |path|. |
-std::wstring& AppendChromeInstallSubDirectory(const InstallConstants& mode, |
- bool include_suffix, |
- std::wstring* path) { |
- if (*kCompanyPathName) { |
- path->append(kCompanyPathName); |
- path->push_back(L'\\'); |
- } |
- path->append(kProductPathName, kProductPathNameLength); |
- if (!include_suffix) |
- return *path; |
- return path->append(mode.install_suffix); |
-} |
- |
bool ReportingIsEnforcedByPolicy(bool* crash_reporting_enabled) { |
std::wstring policies_path = L"SOFTWARE\\Policies\\"; |
- AppendChromeInstallSubDirectory(InstallDetails::Get().mode(), |
- false /* !include_suffix */, &policies_path); |
+ AppendChromeInstallSubDirectory(&policies_path, false /* !include_suffix */); |
DWORD value = 0; |
// First, try HKLM. |
@@ -433,15 +473,45 @@ |
return g_process_type == ProcessType::NON_BROWSER_PROCESS; |
} |
-std::wstring GetCrashDumpLocation() { |
- // In order to be able to start crash handling very early and in chrome_elf, |
- // we cannot rely on chrome's PathService entries (for DIR_CRASH_DUMPS) being |
- // available on Windows. See https://crbug.com/564398. |
- std::wstring user_data_dir; |
- bool ret = GetUserDataDirectory(&user_data_dir, nullptr); |
- assert(ret); |
- IgnoreUnused(ret); |
- return user_data_dir.append(L"\\Crashpad"); |
+bool GetDefaultUserDataDirectory(std::wstring* result) { |
+ // This environment variable should be set on Windows Vista and later |
+ // (https://msdn.microsoft.com/library/windows/desktop/dd378457.aspx). |
+ std::wstring user_data_dir = GetEnvironmentString16(L"LOCALAPPDATA"); |
+ |
+ if (user_data_dir.empty()) { |
+ // LOCALAPPDATA was not set; fallback to the temporary files path. |
+ DWORD size = ::GetTempPath(0, nullptr); |
+ if (!size) |
+ return false; |
+ user_data_dir.resize(size + 1); |
+ size = ::GetTempPath(size + 1, &user_data_dir[0]); |
+ if (!size || size >= user_data_dir.size()) |
+ return false; |
+ user_data_dir.resize(size); |
+ } |
+ |
+ result->swap(user_data_dir); |
+ if ((*result)[result->length() - 1] != L'\\') |
+ result->push_back(L'\\'); |
+ AppendChromeInstallSubDirectory(result, true /* include_suffix */); |
+ result->push_back(L'\\'); |
+ result->append(kUserDataDirname); |
+ return true; |
+} |
+ |
+bool GetDefaultCrashDumpLocation(std::wstring* crash_dir) { |
+ // In order to be able to start crash handling very early, we do not rely on |
+ // chrome's PathService entries (for DIR_CRASH_DUMPS) being available on |
+ // Windows. See https://crbug.com/564398. |
+ if (!GetDefaultUserDataDirectory(crash_dir)) |
+ return false; |
+ |
+ // We have to make sure the user data dir exists on first run. See |
+ // http://crbug.com/591504. |
+ if (!RecursiveDirectoryCreate(*crash_dir)) |
+ return false; |
+ crash_dir->append(L"\\Crashpad"); |
+ return true; |
} |
std::string GetEnvironmentString(const std::string& variable_name) { |
@@ -581,91 +651,46 @@ |
return TokenizeStringT<std::wstring>(str, delimiter, trim_spaces); |
} |
-std::wstring GetSwitchValueFromCommandLine(const std::wstring& command_line, |
- const std::wstring& switch_name) { |
+std::string GetSwitchValueFromCommandLine(const std::string& command_line, |
+ const std::string& switch_name) { |
assert(!command_line.empty()); |
assert(!switch_name.empty()); |
- std::wstring command_line_copy = command_line; |
+ std::string command_line_copy = command_line; |
// Remove leading and trailing spaces. |
- TrimT<std::wstring>(&command_line_copy); |
+ TrimT<std::string>(&command_line_copy); |
// Find the switch in the command line. If we don't find the switch, return |
// an empty string. |
- std::wstring switch_token = L"--"; |
+ std::string switch_token = "--"; |
switch_token += switch_name; |
- switch_token += L"="; |
+ switch_token += "="; |
size_t switch_offset = command_line_copy.find(switch_token); |
if (switch_offset == std::string::npos) |
- return std::wstring(); |
+ return std::string(); |
// The format is "--<switch name>=blah". Look for a space after the |
// "--<switch name>=" string. If we don't find a space assume that the switch |
// value ends at the end of the command line. |
size_t switch_value_start_offset = switch_offset + switch_token.length(); |
- if (std::wstring(kWhiteSpaces16).find( |
- command_line_copy[switch_value_start_offset]) != std::wstring::npos) { |
+ if (std::string(kWhiteSpaces).find( |
+ command_line_copy[switch_value_start_offset]) != std::string::npos) { |
switch_value_start_offset = command_line_copy.find_first_not_of( |
- GetWhiteSpacesForType<std::wstring>(), switch_value_start_offset); |
- if (switch_value_start_offset == std::wstring::npos) |
- return std::wstring(); |
+ GetWhiteSpacesForType<std::string>(), switch_value_start_offset); |
+ if (switch_value_start_offset == std::string::npos) |
+ return std::string(); |
} |
size_t switch_value_end_offset = |
- command_line_copy.find_first_of(GetWhiteSpacesForType<std::wstring>(), |
+ command_line_copy.find_first_of(GetWhiteSpacesForType<std::string>(), |
switch_value_start_offset); |
- if (switch_value_end_offset == std::wstring::npos) |
+ if (switch_value_end_offset == std::string::npos) |
switch_value_end_offset = command_line_copy.length(); |
- std::wstring switch_value = command_line_copy.substr( |
+ std::string switch_value = command_line_copy.substr( |
switch_value_start_offset, |
switch_value_end_offset - (switch_offset + switch_token.length())); |
- TrimT<std::wstring>(&switch_value); |
+ TrimT<std::string>(&switch_value); |
return switch_value; |
-} |
- |
-bool RecursiveDirectoryCreate(const std::wstring& full_path) { |
- // If the path exists, we've succeeded if it's a directory, failed otherwise. |
- const wchar_t* full_path_str = full_path.c_str(); |
- DWORD file_attributes = ::GetFileAttributes(full_path_str); |
- if (file_attributes != INVALID_FILE_ATTRIBUTES) { |
- if ((file_attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { |
- Trace(L"%hs( %ls directory exists )\n", __func__, full_path_str); |
- return true; |
- } |
- Trace(L"%hs( %ls directory conflicts with an existing file. )\n", __func__, |
- full_path_str); |
- return false; |
- } |
- |
- // Invariant: Path does not exist as file or directory. |
- |
- // Attempt to create the parent recursively. This will immediately return |
- // true if it already exists, otherwise will create all required parent |
- // directories starting with the highest-level missing parent. |
- std::wstring parent_path; |
- std::size_t pos = full_path.find_last_of(L"/\\"); |
- if (pos != std::wstring::npos) { |
- parent_path = full_path.substr(0, pos); |
- if (!RecursiveDirectoryCreate(parent_path)) { |
- Trace(L"Failed to create one of the parent directories"); |
- return false; |
- } |
- } |
- if (!::CreateDirectory(full_path_str, nullptr)) { |
- DWORD error_code = ::GetLastError(); |
- if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path_str)) { |
- // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we |
- // were racing with someone creating the same directory, or a file |
- // with the same path. If the directory exists, we lost the |
- // race to create the same directory. |
- return true; |
- } else { |
- Trace(L"Failed to create directory %ls, last error is %d\n", |
- full_path_str, error_code); |
- return false; |
- } |
- } |
- return true; |
} |
// This function takes these inputs rather than accessing the module's |