| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <windows.h> | |
| 6 #include <initguid.h> | |
| 7 | |
| 8 #include "base/at_exit.h" | |
| 9 #include "base/base_paths.h" | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/command_line.h" | |
| 12 #include "base/i18n/streaming_utf8_validator.h" | |
| 13 #include "base/json/json_reader.h" | |
| 14 #include "base/logging.h" | |
| 15 #include "base/logging_win.h" | |
| 16 #include "base/path_service.h" | |
| 17 #include "base/process/launch.h" | |
| 18 #include "base/strings/sys_string_conversions.h" | |
| 19 #include "base/values.h" | |
| 20 #include "chrome/app_installer/win/app_installer_util.h" | |
| 21 #include "chrome/common/chrome_switches.h" | |
| 22 #include "chrome/common/chrome_version_info.h" | |
| 23 #include "chrome/installer/launcher_support/chrome_launcher_support.h" | |
| 24 #include "chrome/installer/util/util_constants.h" | |
| 25 #include "content/public/common/user_agent.h" | |
| 26 | |
| 27 namespace app_installer { | |
| 28 | |
| 29 namespace { | |
| 30 | |
| 31 // Log provider UUID. Required for logging to Sawbuck. | |
| 32 // {d82c3b59-bacd-4625-8282-4d570c4dad12} | |
| 33 DEFINE_GUID(kAppInstallerLogProvider, | |
| 34 0xd82c3b59, | |
| 35 0xbacd, | |
| 36 0x4625, | |
| 37 0x82, 0x82, 0x4d, 0x57, 0x0c, 0x4d, 0xad, 0x12); | |
| 38 | |
| 39 const wchar_t kChromeServer[] = L"chrome.google.com"; | |
| 40 | |
| 41 const wchar_t kInlineInstallDetail[] = L"/webstore/inlineinstall/detail/"; | |
| 42 | |
| 43 } // namespace | |
| 44 | |
| 45 extern "C" | |
| 46 int WINAPI wWinMain(HINSTANCE instance, | |
| 47 HINSTANCE prev_instance, | |
| 48 wchar_t* command_line, | |
| 49 int show_command) { | |
| 50 base::AtExitManager exit_manager; | |
| 51 base::CommandLine::Init(0, NULL); | |
| 52 logging::LogEventProvider::Initialize(kAppInstallerLogProvider); | |
| 53 logging::LoggingSettings settings; | |
| 54 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; | |
| 55 logging::InitLogging(settings); | |
| 56 | |
| 57 std::string app_id = | |
| 58 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | |
| 59 switches::kAppId); | |
| 60 const char* sxs = installer::switches::kChromeSxS; | |
| 61 // --chrome-sxs on the command line takes precedence over chrome-sxs in the | |
| 62 // tag. | |
| 63 bool is_canary = base::CommandLine::ForCurrentProcess()->HasSwitch(sxs); | |
| 64 | |
| 65 // --app-id on the command line inhibits tag parsing altogether. | |
| 66 if (app_id.empty()) { | |
| 67 base::FilePath current_exe; | |
| 68 if (!PathService::Get(base::FILE_EXE, ¤t_exe)) | |
| 69 return COULD_NOT_GET_FILE_PATH; | |
| 70 | |
| 71 // Get the tag added by dl.google.com. Note that this is passed in via URL | |
| 72 // parameters when requesting a file to download, so it must be validated | |
| 73 // before use. | |
| 74 std::string tag = GetTag(current_exe); | |
| 75 if (tag.empty()) | |
| 76 return COULD_NOT_READ_TAG; | |
| 77 | |
| 78 DVLOG(1) << "Tag: " << tag; | |
| 79 | |
| 80 std::map<std::string, std::string> parsed_pairs; | |
| 81 if (!ParseTag(tag, &parsed_pairs)) | |
| 82 return COULD_NOT_PARSE_TAG; | |
| 83 | |
| 84 auto result = parsed_pairs.find(switches::kAppId); | |
| 85 if (result != parsed_pairs.end()) | |
| 86 app_id = result->second; | |
| 87 | |
| 88 if (!is_canary) { | |
| 89 result = parsed_pairs.find(sxs); | |
| 90 is_canary = result != parsed_pairs.end() && result->second == "1"; | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 if (!IsValidAppId(app_id)) | |
| 95 return INVALID_APP_ID; | |
| 96 | |
| 97 // Get the inline install data for this app. We need to set the user agent | |
| 98 // string to be Chrome's, otherwise webstore will serve a different response | |
| 99 // (since inline installs don't work on non-Chrome). | |
| 100 std::vector<uint8_t> response_data; | |
| 101 if (!FetchUrl(base::SysUTF8ToWide(content::BuildUserAgentFromProduct( | |
| 102 chrome::VersionInfo().ProductNameAndVersionForUserAgent())), | |
| 103 kChromeServer, 0, | |
| 104 kInlineInstallDetail + base::SysUTF8ToWide(app_id), | |
| 105 &response_data) || | |
| 106 response_data.empty()) { | |
| 107 return COULD_NOT_FETCH_INLINE_INSTALL_DATA; | |
| 108 } | |
| 109 | |
| 110 // Check that the response is valid UTF-8. | |
| 111 std::string inline_install_json(response_data.begin(), response_data.end()); | |
| 112 if (!base::StreamingUtf8Validator::Validate(inline_install_json)) | |
| 113 return COULD_NOT_PARSE_INLINE_INSTALL_DATA; | |
| 114 | |
| 115 // Parse the data to check it's valid JSON. The download page will just eval | |
| 116 // it. | |
| 117 base::JSONReader json_reader; | |
| 118 scoped_ptr<base::Value> inline_install_data( | |
| 119 json_reader.ReadToValue(inline_install_json)); | |
| 120 if (!inline_install_data) { | |
| 121 LOG(ERROR) << json_reader.GetErrorMessage(); | |
| 122 return COULD_NOT_PARSE_INLINE_INSTALL_DATA; | |
| 123 } | |
| 124 | |
| 125 base::FilePath chrome_path = | |
| 126 chrome_launcher_support::GetAnyChromePath(is_canary); | |
| 127 // If none found, show EULA, download, and install Chrome. | |
| 128 if (chrome_path.empty()) { | |
| 129 ExitCode get_chrome_result = GetChrome(is_canary, inline_install_json); | |
| 130 if (get_chrome_result != SUCCESS) | |
| 131 return get_chrome_result; | |
| 132 | |
| 133 chrome_path = chrome_launcher_support::GetAnyChromePath(is_canary); | |
| 134 if (chrome_path.empty()) | |
| 135 return COULD_NOT_FIND_CHROME; | |
| 136 } | |
| 137 | |
| 138 base::CommandLine cmd(chrome_path); | |
| 139 cmd.AppendSwitchASCII(kInstallChromeApp, app_id); | |
| 140 DVLOG(1) << "Install command: " << cmd.GetCommandLineString(); | |
| 141 bool launched = base::LaunchProcess(cmd, base::LaunchOptions()).IsValid(); | |
| 142 DVLOG(1) << "Launch " << (launched ? "success." : "failed."); | |
| 143 | |
| 144 return SUCCESS; | |
| 145 } | |
| 146 | |
| 147 } // namespace app_installer | |
| OLD | NEW |