chrome_restart_request.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Copyright 2013 The Chromium Authors. All rights reserved. 26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Use of this source code is governed by a BSD-style license that can be 36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// found in the LICENSE file. 46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/chromeos/login/chrome_restart_request.h" 66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include <vector> 86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org 96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "ash/ash_switches.h" 106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/command_line.h" 116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/memory/weak_ptr.h" 126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/message_loop/message_loop.h" 136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/path_service.h" 146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/prefs/json_pref_store.h" 156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/prefs/pref_service.h" 166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/process/launch.h" 176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/strings/string_split.h" 186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/strings/stringprintf.h" 196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/sys_info.h" 20#include "base/timer/timer.h" 21#include "base/values.h" 22#include "cc/base/switches.h" 23#include "chrome/browser/browser_process.h" 24#include "chrome/browser/chromeos/login/user_manager.h" 25#include "chrome/browser/lifetime/application_lifetime.h" 26#include "chrome/common/chrome_constants.h" 27#include "chrome/common/chrome_paths.h" 28#include "chrome/common/chrome_switches.h" 29#include "chrome/common/url_constants.h" 30#include "chromeos/chromeos_switches.h" 31#include "chromeos/dbus/dbus_thread_manager.h" 32#include "chromeos/dbus/session_manager_client.h" 33#include "components/policy/core/common/policy_switches.h" 34#include "content/public/browser/browser_thread.h" 35#include "content/public/common/content_switches.h" 36#include "gpu/command_buffer/service/gpu_switches.h" 37#include "media/base/media_switches.h" 38#include "third_party/cros_system_api/switches/chrome_switches.h" 39#include "ui/app_list/app_list_switches.h" 40#include "ui/base/ui_base_switches.h" 41#include "ui/compositor/compositor_switches.h" 42#include "ui/events/event_switches.h" 43#include "ui/gfx/switches.h" 44#include "ui/gl/gl_switches.h" 45#include "ui/ozone/ozone_switches.h" 46#include "ui/wm/core/wm_core_switches.h" 47#include "url/gurl.h" 48 49using content::BrowserThread; 50 51namespace chromeos { 52 53namespace { 54 55// Increase logging level for Guest mode to avoid INFO messages in logs. 56const char kGuestModeLoggingLevel[] = "1"; 57 58// Format of command line switch. 59const char kSwitchFormatString[] = " --%s=\"%s\""; 60 61// Derives the new command line from |base_command_line| by doing the following: 62// - Forward a given switches list to new command; 63// - Set start url if given; 64// - Append/override switches using |new_switches|; 65std::string DeriveCommandLine(const GURL& start_url, 66 const CommandLine& base_command_line, 67 const base::DictionaryValue& new_switches, 68 CommandLine* command_line) { 69 DCHECK_NE(&base_command_line, command_line); 70 71 static const char* kForwardSwitches[] = { 72 ::switches::kDisableAccelerated2dCanvas, 73 ::switches::kDisableAcceleratedOverflowScroll, 74 ::switches::kDisableAcceleratedVideoDecode, 75 ::switches::kDisableDelegatedRenderer, 76 ::switches::kDisableFastTextAutosizing, 77 ::switches::kDisableFiltersOverIPC, 78 ::switches::kDisableGpuShaderDiskCache, 79 ::switches::kDisableGpuWatchdog, 80 ::switches::kDisableGpuCompositing, 81 ::switches::kDisableGpuRasterization, 82 ::switches::kDisableImplSidePainting, 83 ::switches::kDisableLowResTiling, 84 ::switches::kDisableMediaSource, 85 ::switches::kDisablePrefixedEncryptedMedia, 86 ::switches::kDisablePanelFitting, 87 ::switches::kDisableRepaintAfterLayout, 88 ::switches::kDisableSeccompFilterSandbox, 89 ::switches::kDisableSetuidSandbox, 90 ::switches::kDisableThreadedCompositing, 91 ::switches::kDisableTouchDragDrop, 92 ::switches::kDisableTouchEditing, 93 ::switches::kDisableUniversalAcceleratedOverflowScroll, 94 ::switches::kDisableAcceleratedFixedRootBackground, 95 ::switches::kDisableZeroCopy, 96 ::switches::kEnableAcceleratedFixedRootBackground, 97 ::switches::kEnableAcceleratedOverflowScroll, 98 ::switches::kEnableBeginFrameScheduling, 99 ::switches::kEnableCompositingForFixedPosition, 100 ::switches::kEnableDelegatedRenderer, 101 ::switches::kEnableEncryptedMedia, 102 ::switches::kEnableFastTextAutosizing, 103 ::switches::kEnableGestureTapHighlight, 104 ::switches::kDisableGestureTapHighlight, 105 ::switches::kDisableGpuSandbox, 106 ::switches::kEnableDeferredFilters, 107 ::switches::kEnableContainerCulling, 108 ::switches::kEnableGpuRasterization, 109 ::switches::kEnableImplSidePainting, 110 ::switches::kEnableLogging, 111 ::switches::kEnableLowResTiling, 112 ::switches::kEnableOneCopy, 113 ::switches::kEnablePinch, 114 ::switches::kEnableRepaintAfterLayout, 115 ::switches::kEnableThreadedCompositing, 116 ::switches::kEnableTouchDragDrop, 117 ::switches::kEnableTouchEditing, 118 ::switches::kEnableUniversalAcceleratedOverflowScroll, 119 ::switches::kEnableViewport, 120 ::switches::kEnableViewportMeta, 121 ::switches::kEnableZeroCopy, 122 ::switches::kMainFrameResizesAreOrientationChanges, 123 ::switches::kForceDeviceScaleFactor, 124 ::switches::kForceGpuRasterization, 125 ::switches::kGpuStartupDialog, 126 ::switches::kGpuSandboxAllowSysVShm, 127 ::switches::kGpuSandboxFailuresFatal, 128 ::switches::kGpuSandboxStartAfterInitialization, 129 ::switches::kMultiProfiles, 130 ::switches::kNoSandbox, 131 ::switches::kNumRasterThreads, 132 ::switches::kPpapiFlashArgs, 133 ::switches::kPpapiFlashPath, 134 ::switches::kPpapiFlashVersion, 135 ::switches::kPpapiInProcess, 136 ::switches::kRendererStartupDialog, 137 ::switches::kEnableShareGroupAsyncTextureUpload, 138 ::switches::kTabCaptureUpscaleQuality, 139 ::switches::kTabCaptureDownscaleQuality, 140#if defined(USE_XI2_MT) 141 ::switches::kTouchCalibration, 142#endif 143 ::switches::kTouchDevices, 144 ::switches::kTouchEvents, 145 ::switches::kUIDisableThreadedCompositing, 146 ::switches::kUIPrioritizeInGpuProcess, 147#if defined(USE_CRAS) 148 ::switches::kUseCras, 149#endif 150 ::switches::kUseDiscardableMemory, 151 ::switches::kUseGL, 152 ::switches::kUserDataDir, 153 ::switches::kV, 154 ::switches::kVModule, 155 ::switches::kWebGLCommandBufferSizeKb, 156 ::switches::kEnableWebGLDraftExtensions, 157#if defined(ENABLE_WEBRTC) 158 ::switches::kDisableWebRtcHWDecoding, 159 ::switches::kDisableWebRtcHWEncoding, 160 ::switches::kEnableAudioTrackProcessing, 161 ::switches::kEnableWebRtcHWVp8Encoding, 162#endif 163#if defined(USE_OZONE) 164 ::switches::kOzonePlatform, 165#endif 166 app_list::switches::kDisableSyncAppList, 167 app_list::switches::kEnableSyncAppList, 168 ash::switches::kAshDefaultWallpaperLarge, 169 ash::switches::kAshDefaultWallpaperSmall, 170 ash::switches::kAshGuestWallpaperLarge, 171 ash::switches::kAshGuestWallpaperSmall, 172 ash::switches::kAshHostWindowBounds, 173 ash::switches::kAshTouchHud, 174 ash::switches::kAuraLegacyPowerButton, 175 // Please keep these in alphabetical order. Non-UI Compositor switches 176 // here should also be added to 177 // content/browser/renderer_host/render_process_host_impl.cc. 178 cc::switches::kCompositeToMailbox, 179 cc::switches::kDisableCompositedAntialiasing, 180 cc::switches::kDisableCompositorTouchHitTesting, 181 cc::switches::kDisableMainFrameBeforeActivation, 182 cc::switches::kDisableMainFrameBeforeDraw, 183 cc::switches::kDisablePinchVirtualViewport, 184 cc::switches::kDisableThreadedAnimation, 185 cc::switches::kEnableGpuBenchmarking, 186 cc::switches::kEnablePinchVirtualViewport, 187 cc::switches::kEnableMainFrameBeforeActivation, 188 cc::switches::kEnableTopControlsPositionCalculation, 189 cc::switches::kMaxTilesForInterestArea, 190 cc::switches::kMaxUnusedResourceMemoryUsagePercentage, 191 cc::switches::kShowCompositedLayerBorders, 192 cc::switches::kShowFPSCounter, 193 cc::switches::kShowLayerAnimationBounds, 194 cc::switches::kShowNonOccludingRects, 195 cc::switches::kShowOccludingRects, 196 cc::switches::kShowPropertyChangedRects, 197 cc::switches::kShowReplicaScreenSpaceRects, 198 cc::switches::kShowScreenSpaceRects, 199 cc::switches::kShowSurfaceDamageRects, 200 cc::switches::kSlowDownRasterScaleFactor, 201 cc::switches::kUIDisablePartialSwap, 202 chromeos::switches::kConsumerDeviceManagementUrl, 203 chromeos::switches::kDbusStub, 204 chromeos::switches::kDisableLoginAnimations, 205 chromeos::switches::kEnableConsumerManagement, 206 chromeos::switches::kHasChromeOSDiamondKey, 207 chromeos::switches::kHasChromeOSKeyboard, 208 chromeos::switches::kLoginProfile, 209 chromeos::switches::kNaturalScrollDefault, 210 chromeos::switches::kSystemInDevMode, 211 policy::switches::kDeviceManagementUrl, 212 ::switches::kEnableBrowserTextSubpixelPositioning, 213 ::switches::kEnableWebkitTextSubpixelPositioning, 214 wm::switches::kWindowAnimationsDisabled, 215 }; 216 command_line->CopySwitchesFrom(base_command_line, 217 kForwardSwitches, 218 arraysize(kForwardSwitches)); 219 220 if (start_url.is_valid()) 221 command_line->AppendArg(start_url.spec()); 222 223 for (base::DictionaryValue::Iterator it(new_switches); 224 !it.IsAtEnd(); 225 it.Advance()) { 226 std::string value; 227 CHECK(it.value().GetAsString(&value)); 228 command_line->AppendSwitchASCII(it.key(), value); 229 } 230 231 std::string cmd_line_str = command_line->GetCommandLineString(); 232 // Special workaround for the arguments that should be quoted. 233 // Copying switches won't be needed when Guest mode won't need restart 234 // http://crosbug.com/6924 235 if (base_command_line.HasSwitch(::switches::kRegisterPepperPlugins)) { 236 cmd_line_str += base::StringPrintf( 237 kSwitchFormatString, 238 ::switches::kRegisterPepperPlugins, 239 base_command_line.GetSwitchValueNative( 240 ::switches::kRegisterPepperPlugins).c_str()); 241 } 242 243 return cmd_line_str; 244} 245 246// Simulates a session manager restart by launching give command line 247// and exit current process. 248void ReLaunch(const std::string& command_line) { 249 std::vector<std::string> argv; 250 251 // This is not a proper way to get |argv| but it's good enough for debugging. 252 base::SplitString(command_line, ' ', &argv); 253 254 base::LaunchProcess(argv, base::LaunchOptions(), NULL); 255 chrome::AttemptUserExit(); 256} 257 258// Empty function that run by the local state task runner to ensure last 259// commit goes through. 260void EnsureLocalStateIsWritten() {} 261 262// Wraps the work of sending chrome restart request to session manager. 263// If local state is present, try to commit it first. The request is fired when 264// the commit goes through or some time (3 seconds) has elapsed. 265class ChromeRestartRequest 266 : public base::SupportsWeakPtr<ChromeRestartRequest> { 267 public: 268 explicit ChromeRestartRequest(const std::string& command_line); 269 ~ChromeRestartRequest(); 270 271 // Starts the request. 272 void Start(); 273 274 private: 275 // Fires job restart request to session manager. 276 void RestartJob(); 277 278 const int pid_; 279 const std::string command_line_; 280 base::OneShotTimer<ChromeRestartRequest> timer_; 281 282 DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest); 283}; 284 285ChromeRestartRequest::ChromeRestartRequest(const std::string& command_line) 286 : pid_(getpid()), 287 command_line_(command_line) {} 288 289ChromeRestartRequest::~ChromeRestartRequest() {} 290 291void ChromeRestartRequest::Start() { 292 VLOG(1) << "Requesting a restart with PID " << pid_ 293 << " and command line: " << command_line_; 294 295 // Session Manager may kill the chrome anytime after this point. 296 // Write exit_cleanly and other stuff to the disk here. 297 g_browser_process->EndSession(); 298 299 PrefService* local_state = g_browser_process->local_state(); 300 if (!local_state) { 301 RestartJob(); 302 return; 303 } 304 305 // XXX: normally this call must not be needed, however RestartJob 306 // just kills us so settings may be lost. See http://crosbug.com/13102 307 local_state->CommitPendingWrite(); 308 timer_.Start( 309 FROM_HERE, base::TimeDelta::FromSeconds(3), this, 310 &ChromeRestartRequest::RestartJob); 311 312 // Post a task to local state task runner thus it occurs last on the task 313 // queue, so it would be executed after committing pending write on that 314 // thread. 315 scoped_refptr<base::SequencedTaskRunner> local_state_task_runner = 316 JsonPrefStore::GetTaskRunnerForFile( 317 base::FilePath(chrome::kLocalStorePoolName), 318 BrowserThread::GetBlockingPool()); 319 local_state_task_runner->PostTaskAndReply( 320 FROM_HERE, 321 base::Bind(&EnsureLocalStateIsWritten), 322 base::Bind(&ChromeRestartRequest::RestartJob, AsWeakPtr())); 323} 324 325void ChromeRestartRequest::RestartJob() { 326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 327 328 DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob( 329 pid_, command_line_); 330 331 delete this; 332} 333 334} // namespace 335 336std::string GetOffTheRecordCommandLine( 337 const GURL& start_url, 338 bool is_oobe_completed, 339 const CommandLine& base_command_line, 340 CommandLine* command_line) { 341 base::DictionaryValue otr_switches; 342 otr_switches.SetString(switches::kGuestSession, std::string()); 343 otr_switches.SetString(::switches::kIncognito, std::string()); 344 otr_switches.SetString(::switches::kLoggingLevel, kGuestModeLoggingLevel); 345 otr_switches.SetString(switches::kLoginUser, UserManager::kGuestUserName); 346 347 // Override the home page. 348 otr_switches.SetString(::switches::kHomePage, 349 GURL(chrome::kChromeUINewTabURL).spec()); 350 351 // If OOBE is not finished yet, lock down the guest session to not allow 352 // surfing the web. Guest mode is still useful to inspect logs and run network 353 // diagnostics. 354 if (!is_oobe_completed) 355 otr_switches.SetString(switches::kOobeGuestSession, std::string()); 356 357 return DeriveCommandLine(start_url, 358 base_command_line, 359 otr_switches, 360 command_line); 361} 362 363void RestartChrome(const std::string& command_line) { 364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 365 366 static bool restart_requested = false; 367 if (restart_requested) { 368 NOTREACHED() << "Request chrome restart for more than once."; 369 } 370 restart_requested = true; 371 372 if (!base::SysInfo::IsRunningOnChromeOS()) { 373 // Relaunch chrome without session manager on dev box. 374 ReLaunch(command_line); 375 return; 376 } 377 378 // ChromeRestartRequest deletes itself after request sent to session manager. 379 (new ChromeRestartRequest(command_line))->Start(); 380} 381 382} // namespace chromeos 383