1 // Copyright 2013 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/browser/chromeos/login/chrome_restart_request.h"
9 #include "ash/ash_switches.h"
10 #include "base/command_line.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/prefs/json_pref_store.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/process/launch.h"
16 #include "base/strings/string_split.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/sys_info.h"
19 #include "base/timer/timer.h"
20 #include "base/values.h"
21 #include "cc/base/switches.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/chromeos/boot_times_recorder.h"
24 #include "chrome/browser/lifetime/application_lifetime.h"
25 #include "chrome/common/chrome_constants.h"
26 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/url_constants.h"
29 #include "chromeos/chromeos_switches.h"
30 #include "chromeos/dbus/dbus_thread_manager.h"
31 #include "chromeos/dbus/session_manager_client.h"
32 #include "chromeos/login/user_names.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/public/ozone_switches.h"
46 #include "ui/wm/core/wm_core_switches.h"
49 using content::BrowserThread
;
55 // Increase logging level for Guest mode to avoid INFO messages in logs.
56 const char kGuestModeLoggingLevel
[] = "1";
58 // Format of command line switch.
59 const char kSwitchFormatString
[] = " --%s=\"%s\"";
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|;
65 std::string
DeriveCommandLine(const GURL
& start_url
,
66 const base::CommandLine
& base_command_line
,
67 const base::DictionaryValue
& new_switches
,
68 base::CommandLine
* command_line
) {
69 DCHECK_NE(&base_command_line
, command_line
);
71 static const char* const kForwardSwitches
[] = {
72 ::switches::kDisableAccelerated2dCanvas
,
73 ::switches::kDisableAcceleratedJpegDecoding
,
74 ::switches::kDisableAcceleratedVideoDecode
,
75 ::switches::kDisableBlinkFeatures
,
76 ::switches::kDisableCastStreamingHWEncoding
,
77 ::switches::kDisableDelegatedRenderer
,
78 ::switches::kDisableDistanceFieldText
,
79 ::switches::kDisableGpu
,
80 ::switches::kDisableGpuShaderDiskCache
,
81 ::switches::kDisableGpuWatchdog
,
82 ::switches::kDisableGpuCompositing
,
83 ::switches::kDisableGpuRasterization
,
84 ::switches::kDisableImplSidePainting
,
85 ::switches::kDisableLowResTiling
,
86 ::switches::kDisableMediaSource
,
87 ::switches::kDisableOneCopy
,
88 ::switches::kDisablePreferCompositingToLCDText
,
89 ::switches::kDisablePrefixedEncryptedMedia
,
90 ::switches::kDisablePanelFitting
,
91 ::switches::kDisableSeccompFilterSandbox
,
92 ::switches::kDisableSetuidSandbox
,
93 ::switches::kDisableSurfaces
,
94 ::switches::kDisableTextBlobs
,
95 ::switches::kDisableThreadedGpuRasterization
,
96 ::switches::kDisableThreadedScrolling
,
97 ::switches::kDisableTouchDragDrop
,
98 ::switches::kDisableTouchEditing
,
99 ::switches::kEnableBeginFrameScheduling
,
100 ::switches::kEnableBlinkFeatures
,
101 ::switches::kEnablePreferCompositingToLCDText
,
102 ::switches::kEnableDelegatedRenderer
,
103 ::switches::kDisableDisplayList2dCanvas
,
104 ::switches::kEnableDisplayList2dCanvas
,
105 ::switches::kForceDisplayList2dCanvas
,
106 ::switches::kDisableEncryptedMedia
,
107 ::switches::kDisableGpuSandbox
,
108 ::switches::kEnableDistanceFieldText
,
109 ::switches::kEnableGpuRasterization
,
110 ::switches::kEnableImageColorProfiles
,
111 ::switches::kEnableLogging
,
112 ::switches::kEnableLowResTiling
,
113 ::switches::kEnableOneCopy
,
114 ::switches::kEnablePinch
,
115 ::switches::kEnablePluginPlaceholderShadowDom
,
116 ::switches::kEnableSlimmingPaint
,
117 ::switches::kEnableThreadedGpuRasterization
,
118 ::switches::kEnableTouchDragDrop
,
119 ::switches::kEnableTouchEditing
,
120 ::switches::kEnableViewport
,
121 ::switches::kEnableViewportMeta
,
122 ::switches::kEnableZeroCopy
,
123 ::switches::kMainFrameResizesAreOrientationChanges
,
124 ::switches::kForceDeviceScaleFactor
,
125 ::switches::kForceGpuRasterization
,
126 ::switches::kGpuRasterizationMSAASampleCount
,
127 ::switches::kGpuStartupDialog
,
128 ::switches::kGpuSandboxAllowSysVShm
,
129 ::switches::kGpuSandboxFailuresFatal
,
130 ::switches::kGpuSandboxStartEarly
,
131 ::switches::kIgnoreResolutionLimitsForAcceleratedVideoDecode
,
132 ::switches::kNoSandbox
,
133 ::switches::kNumRasterThreads
,
134 ::switches::kPpapiFlashArgs
,
135 ::switches::kPpapiFlashPath
,
136 ::switches::kPpapiFlashVersion
,
137 ::switches::kPpapiInProcess
,
138 ::switches::kRendererStartupDialog
,
139 ::switches::kRootLayerScrolls
,
140 ::switches::kEnableShareGroupAsyncTextureUpload
,
141 ::switches::kTabCaptureUpscaleQuality
,
142 ::switches::kTabCaptureDownscaleQuality
,
143 #if defined(USE_X11) || defined(USE_OZONE)
144 ::switches::kTouchCalibration
,
146 ::switches::kTouchDevices
,
147 ::switches::kTouchEvents
,
148 ::switches::kUIDisableThreadedCompositing
,
149 ::switches::kUIPrioritizeInGpuProcess
,
150 #if defined(USE_CRAS)
151 ::switches::kUseCras
,
153 ::switches::kUseDiscardableMemory
,
155 ::switches::kUseNormalPriorityForTileTaskWorkerThreads
,
156 ::switches::kUserDataDir
,
158 ::switches::kVModule
,
159 ::switches::kEnableWebGLDraftExtensions
,
160 ::switches::kEnableWebGLImageChromium
,
161 #if defined(ENABLE_WEBRTC)
162 ::switches::kDisableWebRtcHWDecoding
,
163 ::switches::kDisableWebRtcHWEncoding
,
164 ::switches::kEnableWebRtcHWH264Encoding
,
166 ::switches::kDisableVaapiAcceleratedVideoEncode
,
167 #if defined(USE_OZONE)
168 ::switches::kOzoneInitialDisplayBounds
,
169 ::switches::kOzoneInitialDisplayPhysicalSizeMm
,
170 ::switches::kOzonePlatform
,
171 ::switches::kOzoneUseSurfaceless
,
173 app_list::switches::kDisableSyncAppList
,
174 app_list::switches::kEnableSyncAppList
,
175 ash::switches::kAshHostWindowBounds
,
176 ash::switches::kAshTouchHud
,
177 ash::switches::kAuraLegacyPowerButton
,
178 chromeos::switches::kDefaultWallpaperLarge
,
179 chromeos::switches::kDefaultWallpaperSmall
,
180 chromeos::switches::kGuestWallpaperLarge
,
181 chromeos::switches::kGuestWallpaperSmall
,
182 // Please keep these in alphabetical order. Non-UI Compositor switches
183 // here should also be added to
184 // content/browser/renderer_host/render_process_host_impl.cc.
185 cc::switches::kCompositeToMailbox
,
186 cc::switches::kDisableCompositedAntialiasing
,
187 cc::switches::kDisableMainFrameBeforeActivation
,
188 cc::switches::kDisablePinchVirtualViewport
,
189 cc::switches::kDisableThreadedAnimation
,
190 cc::switches::kEnableGpuBenchmarking
,
191 cc::switches::kEnablePinchVirtualViewport
,
192 cc::switches::kEnablePropertyTreeVerification
,
193 cc::switches::kEnableMainFrameBeforeActivation
,
194 cc::switches::kEnableTopControlsPositionCalculation
,
195 cc::switches::kMaxTilesForInterestArea
,
196 cc::switches::kMaxUnusedResourceMemoryUsagePercentage
,
197 cc::switches::kShowCompositedLayerBorders
,
198 cc::switches::kShowFPSCounter
,
199 cc::switches::kShowLayerAnimationBounds
,
200 cc::switches::kShowPropertyChangedRects
,
201 cc::switches::kShowReplicaScreenSpaceRects
,
202 cc::switches::kShowScreenSpaceRects
,
203 cc::switches::kShowSurfaceDamageRects
,
204 cc::switches::kSlowDownRasterScaleFactor
,
205 cc::switches::kUIDisablePartialSwap
,
206 chromeos::switches::kConsumerDeviceManagementUrl
,
207 chromeos::switches::kDbusStub
,
208 chromeos::switches::kDbusUnstubClients
,
209 chromeos::switches::kDisableLoginAnimations
,
210 chromeos::switches::kEnableConsumerManagement
,
211 chromeos::switches::kEnterpriseEnableForcedReEnrollment
,
212 chromeos::switches::kHasChromeOSDiamondKey
,
213 chromeos::switches::kHasChromeOSKeyboard
,
214 chromeos::switches::kLoginProfile
,
215 chromeos::switches::kNaturalScrollDefault
,
216 chromeos::switches::kSystemInDevMode
,
217 policy::switches::kDeviceManagementUrl
,
218 ::switches::kEnableWebkitTextSubpixelPositioning
,
219 wm::switches::kWindowAnimationsDisabled
,
221 command_line
->CopySwitchesFrom(base_command_line
,
223 arraysize(kForwardSwitches
));
225 if (start_url
.is_valid())
226 command_line
->AppendArg(start_url
.spec());
228 for (base::DictionaryValue::Iterator
it(new_switches
);
232 CHECK(it
.value().GetAsString(&value
));
233 command_line
->AppendSwitchASCII(it
.key(), value
);
236 std::string cmd_line_str
= command_line
->GetCommandLineString();
237 // Special workaround for the arguments that should be quoted.
238 // Copying switches won't be needed when Guest mode won't need restart
239 // http://crosbug.com/6924
240 if (base_command_line
.HasSwitch(::switches::kRegisterPepperPlugins
)) {
241 cmd_line_str
+= base::StringPrintf(
243 ::switches::kRegisterPepperPlugins
,
244 base_command_line
.GetSwitchValueNative(
245 ::switches::kRegisterPepperPlugins
).c_str());
251 // Simulates a session manager restart by launching give command line
252 // and exit current process.
253 void ReLaunch(const std::string
& command_line
) {
254 std::vector
<std::string
> argv
;
256 // This is not a proper way to get |argv| but it's good enough for debugging.
257 base::SplitString(command_line
, ' ', &argv
);
259 base::LaunchProcess(argv
, base::LaunchOptions());
260 chrome::AttemptUserExit();
263 // Empty function that run by the local state task runner to ensure last
264 // commit goes through.
265 void EnsureLocalStateIsWritten() {}
267 // Wraps the work of sending chrome restart request to session manager.
268 // If local state is present, try to commit it first. The request is fired when
269 // the commit goes through or some time (3 seconds) has elapsed.
270 class ChromeRestartRequest
271 : public base::SupportsWeakPtr
<ChromeRestartRequest
> {
273 explicit ChromeRestartRequest(const std::string
& command_line
);
274 ~ChromeRestartRequest();
276 // Starts the request.
280 // Fires job restart request to session manager.
284 const std::string command_line_
;
285 base::OneShotTimer
<ChromeRestartRequest
> timer_
;
287 DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest
);
290 ChromeRestartRequest::ChromeRestartRequest(const std::string
& command_line
)
292 command_line_(command_line
) {}
294 ChromeRestartRequest::~ChromeRestartRequest() {}
296 void ChromeRestartRequest::Start() {
297 VLOG(1) << "Requesting a restart with PID " << pid_
298 << " and command line: " << command_line_
;
300 // Session Manager may kill the chrome anytime after this point.
301 // Write exit_cleanly and other stuff to the disk here.
302 g_browser_process
->EndSession();
304 PrefService
* local_state
= g_browser_process
->local_state();
310 // XXX: normally this call must not be needed, however RestartJob
311 // just kills us so settings may be lost. See http://crosbug.com/13102
312 local_state
->CommitPendingWrite();
314 FROM_HERE
, base::TimeDelta::FromSeconds(3), this,
315 &ChromeRestartRequest::RestartJob
);
317 // Post a task to local state task runner thus it occurs last on the task
318 // queue, so it would be executed after committing pending write on that
320 scoped_refptr
<base::SequencedTaskRunner
> local_state_task_runner
=
321 JsonPrefStore::GetTaskRunnerForFile(
322 base::FilePath(chrome::kLocalStorePoolName
),
323 BrowserThread::GetBlockingPool());
324 local_state_task_runner
->PostTaskAndReply(
326 base::Bind(&EnsureLocalStateIsWritten
),
327 base::Bind(&ChromeRestartRequest::RestartJob
, AsWeakPtr()));
330 void ChromeRestartRequest::RestartJob() {
331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
333 DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob(
334 pid_
, command_line_
);
341 std::string
GetOffTheRecordCommandLine(
342 const GURL
& start_url
,
343 bool is_oobe_completed
,
344 const base::CommandLine
& base_command_line
,
345 base::CommandLine
* command_line
) {
346 base::DictionaryValue otr_switches
;
347 otr_switches
.SetString(switches::kGuestSession
, std::string());
348 otr_switches
.SetString(::switches::kIncognito
, std::string());
349 otr_switches
.SetString(::switches::kLoggingLevel
, kGuestModeLoggingLevel
);
350 otr_switches
.SetString(switches::kLoginUser
, chromeos::login::kGuestUserName
);
352 // Override the home page.
353 otr_switches
.SetString(::switches::kHomePage
,
354 GURL(chrome::kChromeUINewTabURL
).spec());
356 // If OOBE is not finished yet, lock down the guest session to not allow
357 // surfing the web. Guest mode is still useful to inspect logs and run network
359 if (!is_oobe_completed
)
360 otr_switches
.SetString(switches::kOobeGuestSession
, std::string());
362 return DeriveCommandLine(start_url
,
368 void RestartChrome(const std::string
& command_line
) {
369 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
370 BootTimesRecorder::Get()->set_restart_requested();
372 static bool restart_requested
= false;
373 if (restart_requested
) {
374 NOTREACHED() << "Request chrome restart for more than once.";
376 restart_requested
= true;
378 if (!base::SysInfo::IsRunningOnChromeOS()) {
379 // Relaunch chrome without session manager on dev box.
380 ReLaunch(command_line
);
384 // ChromeRestartRequest deletes itself after request sent to session manager.
385 (new ChromeRestartRequest(command_line
))->Start();
388 } // namespace chromeos