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 |