chrome_launcher.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "cloud_print/service/win/chrome_launcher.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/base_switches.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_util.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/scoped_temp_dir.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_reader.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_writer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/process_util.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/win/registry.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_process_information.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_constants.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/pref_names.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/launcher_support/chrome_launcher_support.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/common/win/cloud_print_utils.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/service/service_constants.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/service/win/service_utils.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "google_apis/gaia/gaia_urls.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/url_util.h" 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kShutdownTimeoutMs = 30 * 1000; 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kUsageUpdateTimeoutMs = 6 * 3600 * 1000; // 6 hours. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static const char16 kAutoRunKeyPath[] = 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) L"Software\\Microsoft\\Windows\\CurrentVersion\\Run"; 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Terminates any process. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShutdownChrome(HANDLE process, DWORD thread_id) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (::PostThreadMessage(thread_id, WM_QUIT, 0, 0) && 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WAIT_OBJECT_0 == ::WaitForSingleObject(process, kShutdownTimeoutMs)) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to shutdown process."; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::KillProcess(process, 0, true); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)BOOL CALLBACK CloseIfPidEqual(HWND wnd, LPARAM lparam) { 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DWORD pid = 0; 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ::GetWindowThreadProcessId(wnd, &pid); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (pid == static_cast<DWORD>(lparam)) 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ::PostMessage(wnd, WM_CLOSE, 0, 0); 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return TRUE; 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CloseAllProcessWindows(HANDLE process) { 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ::EnumWindows(&CloseIfPidEqual, GetProcessId(process)); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Close Chrome browser window. 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CloseChrome(HANDLE process, DWORD thread_id) { 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CloseAllProcessWindows(process); 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (WAIT_OBJECT_0 == ::WaitForSingleObject(process, kShutdownTimeoutMs)) { 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ShutdownChrome(process, thread_id); 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool LaunchProcess(const CommandLine& cmdline, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessHandle* process_handle, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD* thread_id) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STARTUPINFO startup_info = {}; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startup_info.cb = sizeof(startup_info); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startup_info.dwFlags = STARTF_USESHOWWINDOW; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) startup_info.wShowWindow = SW_SHOW; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedProcessInformation process_info; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CreateProcess(NULL, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<wchar_t*>(cmdline.GetCommandLineString().c_str()), NULL, NULL, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE, 0, NULL, NULL, &startup_info, process_info.Receive())) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_handle) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *process_handle = process_info.TakeProcessHandle(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thread_id) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *thread_id = process_info.thread_id(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GetCloudPrintServiceEnableURL(const std::string& proxy_id) { 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL url( 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switches::kCloudPrintServiceURL)); 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (url.is_empty()) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url = GURL("https://www.google.com/cloudprint"); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url = net::AppendQueryParameter(url, "proxy", proxy_id); 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string url_path(url.path() + "/enable_chrome_connector/enable.html"); 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL::Replacements replacements; 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replacements.SetPathStr(url_path); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return url.ReplaceComponents(replacements); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)GURL GetCloudPrintServiceEnableURLWithSignin(const std::string& proxy_id) { 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL url(GaiaUrls::GetInstance()->service_login_url()); 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url = net::AppendQueryParameter(url, "service", "cloudprint"); 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url = net::AppendQueryParameter(url, "sarp", "1"); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return net::AppendQueryParameter( 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) url, "continue", GetCloudPrintServiceEnableURL(proxy_id).spec()); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string ReadAndUpdateServiceState(const base::FilePath& directory, 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& proxy_id) { 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string json; 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath file_path = directory.Append(chrome::kServiceStateFileName); 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!file_util::ReadFileToString(file_path, &json)) { 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<base::Value> service_state(base::JSONReader::Read(json)); 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::DictionaryValue* dictionary = NULL; 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!service_state->GetAsDictionary(&dictionary) || !dictionary) { 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool enabled = false; 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!dictionary->GetBoolean(prefs::kCloudPrintProxyEnabled, &enabled) || 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !enabled) { 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string refresh_token; 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!dictionary->GetString(prefs::kCloudPrintRobotRefreshToken, 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &refresh_token) || 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) refresh_token.empty()) { 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Remove everything except kCloudPrintRoot. 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Value* cloud_print_root = NULL; 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dictionary->Remove(prefs::kCloudPrintRoot, &cloud_print_root); 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dictionary->Clear(); 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dictionary->Set(prefs::kCloudPrintRoot, cloud_print_root); 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dictionary->SetBoolean(prefs::kCloudPrintXmppPingEnabled, true); 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!proxy_id.empty()) // Reuse proxy id if we already had one. 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) dictionary->SetString(prefs::kCloudPrintProxyId, proxy_id); 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string result; 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::JSONWriter::WriteWithOptions(dictionary, 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::JSONWriter::OPTIONS_PRETTY_PRINT, 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) &result); 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeleteAutorunKeys(const base::FilePath& user_data_dir) { 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::RegKey key(HKEY_CURRENT_USER, kAutoRunKeyPath, KEY_SET_VALUE); 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!key.Valid()) 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<string16> to_delete; 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath abs_user_data_dir = base::MakeAbsoluteFilePath(user_data_dir); 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) { 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::RegistryValueIterator value(HKEY_CURRENT_USER, kAutoRunKeyPath); 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (; value.Valid(); ++value) { 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (value.Type() == REG_SZ && value.Value()) { 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CommandLine cmd = CommandLine::FromString(value.Value()); 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (cmd.GetSwitchValueASCII(switches::kProcessType) == 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switches::kServiceProcess && 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.HasSwitch(switches::kUserDataDir)) { 173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath path_from_reg = base::MakeAbsoluteFilePath( 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.GetSwitchValuePath(switches::kUserDataDir)); 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (path_from_reg == abs_user_data_dir) { 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) to_delete.push_back(value.Name()); 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < to_delete.size(); ++i) { 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) key.DeleteValue(to_delete[i].c_str()); 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeLauncher::ChromeLauncher(const base::FilePath& user_data) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : stop_event_(true, true), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_data_(user_data) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeLauncher::~ChromeLauncher() { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChromeLauncher::Start() { 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeleteAutorunKeys(user_data_); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stop_event_.Reset(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_.reset(new base::DelegateSimpleThread(this, "chrome_launcher")); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_->Start(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeLauncher::Stop() { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stop_event_.Signal(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_->Join(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_.reset(); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeLauncher::Run() { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta default_time_out = base::TimeDelta::FromSeconds(1); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::TimeDelta max_time_out = base::TimeDelta::FromHours(1); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (base::TimeDelta time_out = default_time_out;; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_out = std::min(time_out * 2, max_time_out)) { 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath chrome_path = chrome_launcher_support::GetAnyChromePath(); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!chrome_path.empty()) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine cmd(chrome_path); 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CopyChromeSwitchesFromCurrentProcess(&cmd); 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Required switches. 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitchASCII(switches::kProcessType, switches::kServiceProcess); 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitchPath(switches::kUserDataDir, user_data_); 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kNoServiceAutorun); 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Optional. 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kAutoLaunchAtStartup); 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableBackgroundMode); 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableDefaultApps); 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableExtensions); 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableGpu); 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableSoftwareRasterizer); 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableSync); 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kNoFirstRun); 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kNoStartupWindow); 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedHandle chrome_handle; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time started = base::Time::Now(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD thread_id = 0; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LaunchProcess(cmd, chrome_handle.Receive(), &thread_id); 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE handles[] = {stop_event_.handle(), chrome_handle}; 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DWORD wait_result = WAIT_TIMEOUT; 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) while (wait_result == WAIT_TIMEOUT) { 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cloud_print::SetGoogleUpdateUsage(kGoogleUpdateId); 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) wait_result = ::WaitForMultipleObjects(arraysize(handles), handles, 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FALSE, kUsageUpdateTimeoutMs); 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (wait_result == WAIT_OBJECT_0) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShutdownChrome(chrome_handle, thread_id); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (wait_result == WAIT_OBJECT_0 + 1) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Chrome process exited."; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Error waiting Chrome (" << ::GetLastError() << ")."; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::Time::Now() - started > base::TimeDelta::FromHours(1)) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset timeout because process worked long enough. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time_out = default_time_out; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stop_event_.TimedWait(time_out)) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string ChromeLauncher::CreateServiceStateFile( 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& proxy_id, 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::vector<std::string>& printers) { 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string result; 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ScopedTempDir temp_user_data; 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!temp_user_data.CreateUniqueTempDir()) { 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Can't create temp dir."; 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath chrome_path = chrome_launcher_support::GetAnyChromePath(); 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (chrome_path.empty()) { 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Can't find Chrome."; 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath printers_file = temp_user_data.path().Append(L"printers.json"); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ListValue printer_list; 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) printer_list.AppendStrings(printers); 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string printers_json; 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::JSONWriter::Write(&printer_list, &printers_json); 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t written = file_util::WriteFile(printers_file, 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) printers_json.c_str(), 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) printers_json.size()); 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (written != printers_json.size()) { 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Can't write file."; 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CommandLine cmd(chrome_path); 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CopyChromeSwitchesFromCurrentProcess(&cmd); 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitchPath(switches::kUserDataDir, temp_user_data.path()); 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitchPath(switches::kCloudPrintSetupProxy, printers_file); 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kNoServiceAutorun); 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Optional. 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableBackgroundMode); 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableDefaultApps); 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableExtensions); 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kDisableSync); 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kNoDefaultBrowserCheck); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendSwitch(switches::kNoFirstRun); 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cmd.AppendArg(GetCloudPrintServiceEnableURLWithSignin(proxy_id).spec()); 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::win::ScopedHandle chrome_handle; 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DWORD thread_id = 0; 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!LaunchProcess(cmd, chrome_handle.Receive(), &thread_id)) { 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Unable to launch Chrome."; 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (;;) { 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DWORD wait_result = ::WaitForSingleObject(chrome_handle, 500); 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string json = ReadAndUpdateServiceState(temp_user_data.path(), 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) proxy_id); 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (wait_result == WAIT_OBJECT_0) { 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Return what we have because browser is closed. 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return json; 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else if (wait_result == WAIT_TIMEOUT) { 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!json.empty()) { 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Close chrome because Service State is ready. 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CloseChrome(chrome_handle, thread_id); 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return json; 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Chrome launch failed."; 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return result; 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 347