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