chromeos: dbus: add Bluetooth properties support
[chromium-blink-merge.git] / chrome_frame / chrome_launcher.cc
blobe943c7ff05862b71d3a34b61a922606be4ee3719
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
3 // found in the LICENSE file.
5 #include "chrome_frame/chrome_launcher.h"
7 #include <windows.h>
8 #include <shellapi.h>
9 #include <shlwapi.h>
11 // Herein lies stuff selectively stolen from Chrome. We don't pull it in
12 // directly because all of it results in many things we don't want being
13 // included as well.
14 namespace {
16 // These are the switches we will allow (along with their values) in the
17 // safe-for-Low-Integrity version of the Chrome command line.
18 // Including the chrome switch files pulls in a bunch of dependencies sadly, so
19 // we redefine things here:
20 const wchar_t* kAllowedSwitches[] = {
21 L"automation-channel",
22 L"chrome-frame",
23 L"chrome-version",
24 L"disable-background-mode",
25 L"disable-popup-blocking",
26 L"disable-print-preview",
27 L"disable-renderer-accessibility",
28 L"enable-experimental-extension-apis",
29 L"force-renderer-accessibility",
30 L"full-memory-crash-report",
31 L"lang",
32 L"no-default-browser-check",
33 L"no-first-run",
34 L"noerrdialogs",
35 L"user-data-dir",
38 const wchar_t kWhitespaceChars[] = {
39 0x0009, /* <control-0009> to <control-000D> */
40 0x000A,
41 0x000B,
42 0x000C,
43 0x000D,
44 0x0020, /* Space */
45 0x0085, /* <control-0085> */
46 0x00A0, /* No-Break Space */
47 0x1680, /* Ogham Space Mark */
48 0x180E, /* Mongolian Vowel Separator */
49 0x2000, /* En Quad to Hair Space */
50 0x2001,
51 0x2002,
52 0x2003,
53 0x2004,
54 0x2005,
55 0x2006,
56 0x2007,
57 0x2008,
58 0x2009,
59 0x200A,
60 0x200C, /* Zero Width Non-Joiner */
61 0x2028, /* Line Separator */
62 0x2029, /* Paragraph Separator */
63 0x202F, /* Narrow No-Break Space */
64 0x205F, /* Medium Mathematical Space */
65 0x3000, /* Ideographic Space */
69 const wchar_t kLauncherExeBaseName[] = L"chrome_launcher.exe";
70 const wchar_t kBrowserProcessExecutableName[] = L"chrome.exe";
72 } // end namespace
75 namespace chrome_launcher {
77 std::wstring TrimWhiteSpace(const wchar_t* input_str) {
78 std::wstring output;
79 if (input_str != NULL) {
80 std::wstring str(input_str);
82 const std::wstring::size_type first_good_char =
83 str.find_first_not_of(kWhitespaceChars);
84 const std::wstring::size_type last_good_char =
85 str.find_last_not_of(kWhitespaceChars);
87 if (first_good_char != std::wstring::npos &&
88 last_good_char != std::wstring::npos &&
89 last_good_char >= first_good_char) {
90 // + 1 because find_last_not_of returns the index, and we want the count
91 output = str.substr(first_good_char,
92 last_good_char - first_good_char + 1);
96 return output;
99 bool IsValidArgument(const std::wstring& arg) {
100 if (arg.length() < 2) {
101 return false;
104 for (int i = 0; i < arraysize(kAllowedSwitches); ++i) {
105 size_t arg_length = lstrlenW(kAllowedSwitches[i]);
106 if (arg.find(kAllowedSwitches[i], 2) == 2) {
107 // The argument starts off right, now it must either end here, or be
108 // followed by an equals sign.
109 if (arg.length() == (arg_length + 2) ||
110 (arg.length() > (arg_length + 2) && arg[arg_length+2] == L'=')) {
111 return true;
116 return false;
119 bool IsValidCommandLine(const wchar_t* command_line) {
120 if (command_line == NULL) {
121 return false;
124 int num_args = 0;
125 wchar_t** args = NULL;
126 args = CommandLineToArgvW(command_line, &num_args);
128 bool success = true;
129 // Note that we skip args[0] since that is just our executable name and
130 // doesn't get passed through to Chrome.
131 for (int i = 1; i < num_args; ++i) {
132 std::wstring trimmed_arg = TrimWhiteSpace(args[i]);
133 if (!IsValidArgument(trimmed_arg.c_str())) {
134 success = false;
135 break;
139 return success;
142 bool SanitizeAndLaunchChrome(const wchar_t* command_line) {
143 bool success = false;
144 if (IsValidCommandLine(command_line)) {
145 std::wstring chrome_path;
146 if (GetChromeExecutablePath(&chrome_path)) {
147 const wchar_t* args = PathGetArgs(command_line);
149 // Build the command line string with the quoted path to chrome.exe.
150 std::wstring command_line;
151 command_line.reserve(chrome_path.size() + 2);
152 command_line.append(1, L'\"').append(chrome_path).append(1, L'\"');
154 if (args != NULL) {
155 command_line += L' ';
156 command_line += args;
159 STARTUPINFO startup_info = {0};
160 startup_info.cb = sizeof(startup_info);
161 startup_info.dwFlags = STARTF_USESHOWWINDOW;
162 startup_info.wShowWindow = SW_SHOW;
163 PROCESS_INFORMATION process_info = {0};
164 if (CreateProcess(&chrome_path[0], &command_line[0],
165 NULL, NULL, FALSE, 0, NULL, NULL,
166 &startup_info, &process_info)) {
167 // Close handles.
168 CloseHandle(process_info.hThread);
169 CloseHandle(process_info.hProcess);
170 success = true;
171 } else {
172 _ASSERT(FALSE);
177 return success;
180 bool GetChromeExecutablePath(std::wstring* chrome_path) {
181 _ASSERT(chrome_path);
183 wchar_t cur_path[MAX_PATH * 4] = {0};
184 // Assume that we are always built into an exe.
185 GetModuleFileName(NULL, cur_path, arraysize(cur_path) / 2);
187 PathRemoveFileSpec(cur_path);
189 bool success = false;
190 if (PathAppend(cur_path, kBrowserProcessExecutableName)) {
191 if (!PathFileExists(cur_path)) {
192 // The installation model for Chrome places the DLLs in a versioned
193 // sub-folder one down from the Chrome executable. If we fail to find
194 // chrome.exe in the current path, try looking one up and launching that
195 // instead. In practice, that means we back up two and append the
196 // executable name again.
197 PathRemoveFileSpec(cur_path);
198 PathRemoveFileSpec(cur_path);
199 PathAppend(cur_path, kBrowserProcessExecutableName);
202 if (PathFileExists(cur_path)) {
203 *chrome_path = cur_path;
204 success = true;
208 return success;
211 } // namespace chrome_launcher