• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/chromeos/login/chrome_restart_request.h"
6 
7 #include <vector>
8 
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/path_service.h"
14 #include "base/prefs/json_pref_store.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/process/launch.h"
17 #include "base/strings/string_split.h"
18 #include "base/strings/stringprintf.h"
19 #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/boot_times_loader.h"
25 #include "chrome/browser/chromeos/login/users/user_manager.h"
26 #include "chrome/browser/lifetime/application_lifetime.h"
27 #include "chrome/common/chrome_constants.h"
28 #include "chrome/common/chrome_paths.h"
29 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/url_constants.h"
31 #include "chromeos/chromeos_switches.h"
32 #include "chromeos/dbus/dbus_thread_manager.h"
33 #include "chromeos/dbus/session_manager_client.h"
34 #include "components/policy/core/common/policy_switches.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "content/public/common/content_switches.h"
37 #include "gpu/command_buffer/service/gpu_switches.h"
38 #include "media/base/media_switches.h"
39 #include "third_party/cros_system_api/switches/chrome_switches.h"
40 #include "ui/app_list/app_list_switches.h"
41 #include "ui/base/ui_base_switches.h"
42 #include "ui/compositor/compositor_switches.h"
43 #include "ui/events/event_switches.h"
44 #include "ui/gfx/switches.h"
45 #include "ui/gl/gl_switches.h"
46 #include "ui/ozone/ozone_switches.h"
47 #include "ui/wm/core/wm_core_switches.h"
48 #include "url/gurl.h"
49 
50 using content::BrowserThread;
51 
52 namespace chromeos {
53 
54 namespace {
55 
56 // Increase logging level for Guest mode to avoid INFO messages in logs.
57 const char kGuestModeLoggingLevel[] = "1";
58 
59 // Format of command line switch.
60 const char kSwitchFormatString[] = " --%s=\"%s\"";
61 
62 // Derives the new command line from |base_command_line| by doing the following:
63 // - Forward a given switches list to new command;
64 // - Set start url if given;
65 // - Append/override switches using |new_switches|;
DeriveCommandLine(const GURL & start_url,const CommandLine & base_command_line,const base::DictionaryValue & new_switches,CommandLine * command_line)66 std::string DeriveCommandLine(const GURL& start_url,
67                               const CommandLine& base_command_line,
68                               const base::DictionaryValue& new_switches,
69                               CommandLine* command_line) {
70   DCHECK_NE(&base_command_line, command_line);
71 
72   static const char* kForwardSwitches[] = {
73     ::switches::kDisableAccelerated2dCanvas,
74     ::switches::kDisableAcceleratedOverflowScroll,
75     ::switches::kDisableAcceleratedVideoDecode,
76     ::switches::kDisableDelegatedRenderer,
77     ::switches::kDisableDistanceFieldText,
78     ::switches::kDisableFastTextAutosizing,
79     ::switches::kDisableGpuShaderDiskCache,
80     ::switches::kDisableGpuWatchdog,
81     ::switches::kDisableGpuCompositing,
82     ::switches::kDisableGpuRasterization,
83     ::switches::kDisableImplSidePainting,
84     ::switches::kDisableLowResTiling,
85     ::switches::kDisableMediaSource,
86     ::switches::kDisablePrefixedEncryptedMedia,
87     ::switches::kDisablePanelFitting,
88     ::switches::kDisableRepaintAfterLayout,
89     ::switches::kDisableSeccompFilterSandbox,
90     ::switches::kDisableSetuidSandbox,
91     ::switches::kDisableThreadedCompositing,
92     ::switches::kDisableTouchDragDrop,
93     ::switches::kDisableTouchEditing,
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::kDisableDeferredFilters,
107     ::switches::kEnableContainerCulling,
108     ::switches::kEnableDistanceFieldText,
109     ::switches::kEnableGpuRasterization,
110     ::switches::kEnableImplSidePainting,
111     ::switches::kEnableLogging,
112     ::switches::kEnableLowResTiling,
113     ::switches::kEnableOneCopy,
114     ::switches::kEnablePinch,
115     ::switches::kEnableRepaintAfterLayout,
116     ::switches::kEnableThreadedCompositing,
117     ::switches::kEnableTouchDragDrop,
118     ::switches::kEnableTouchEditing,
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::kIgnoreResolutionLimitsForAcceleratedVideoDecode,
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::kEnableWebGLDraftExtensions,
156     ::switches::kEnableWebGLImageChromium,
157 #if defined(ENABLE_WEBRTC)
158     ::switches::kDisableAudioTrackProcessing,
159     ::switches::kDisableWebRtcHWDecoding,
160     ::switches::kDisableWebRtcHWEncoding,
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::kEnterpriseEnableForcedReEnrollment,
207     chromeos::switches::kHasChromeOSDiamondKey,
208     chromeos::switches::kHasChromeOSKeyboard,
209     chromeos::switches::kLoginProfile,
210     chromeos::switches::kNaturalScrollDefault,
211     chromeos::switches::kSystemInDevMode,
212     policy::switches::kDeviceManagementUrl,
213     ::switches::kEnableBrowserTextSubpixelPositioning,
214     ::switches::kEnableWebkitTextSubpixelPositioning,
215     wm::switches::kWindowAnimationsDisabled,
216   };
217   command_line->CopySwitchesFrom(base_command_line,
218                                  kForwardSwitches,
219                                  arraysize(kForwardSwitches));
220 
221   if (start_url.is_valid())
222     command_line->AppendArg(start_url.spec());
223 
224   for (base::DictionaryValue::Iterator it(new_switches);
225        !it.IsAtEnd();
226        it.Advance()) {
227     std::string value;
228     CHECK(it.value().GetAsString(&value));
229     command_line->AppendSwitchASCII(it.key(), value);
230   }
231 
232   std::string cmd_line_str = command_line->GetCommandLineString();
233   // Special workaround for the arguments that should be quoted.
234   // Copying switches won't be needed when Guest mode won't need restart
235   // http://crosbug.com/6924
236   if (base_command_line.HasSwitch(::switches::kRegisterPepperPlugins)) {
237     cmd_line_str += base::StringPrintf(
238         kSwitchFormatString,
239         ::switches::kRegisterPepperPlugins,
240         base_command_line.GetSwitchValueNative(
241             ::switches::kRegisterPepperPlugins).c_str());
242   }
243 
244   return cmd_line_str;
245 }
246 
247 // Simulates a session manager restart by launching give command line
248 // and exit current process.
ReLaunch(const std::string & command_line)249 void ReLaunch(const std::string& command_line) {
250   std::vector<std::string> argv;
251 
252   // This is not a proper way to get |argv| but it's good enough for debugging.
253   base::SplitString(command_line, ' ', &argv);
254 
255   base::LaunchProcess(argv, base::LaunchOptions(), NULL);
256   chrome::AttemptUserExit();
257 }
258 
259 // Empty function that run by the local state task runner to ensure last
260 // commit goes through.
EnsureLocalStateIsWritten()261 void EnsureLocalStateIsWritten() {}
262 
263 // Wraps the work of sending chrome restart request to session manager.
264 // If local state is present, try to commit it first. The request is fired when
265 // the commit goes through or some time (3 seconds) has elapsed.
266 class ChromeRestartRequest
267     : public base::SupportsWeakPtr<ChromeRestartRequest> {
268  public:
269   explicit ChromeRestartRequest(const std::string& command_line);
270   ~ChromeRestartRequest();
271 
272   // Starts the request.
273   void Start();
274 
275  private:
276   // Fires job restart request to session manager.
277   void RestartJob();
278 
279   const int pid_;
280   const std::string command_line_;
281   base::OneShotTimer<ChromeRestartRequest> timer_;
282 
283   DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest);
284 };
285 
ChromeRestartRequest(const std::string & command_line)286 ChromeRestartRequest::ChromeRestartRequest(const std::string& command_line)
287     : pid_(getpid()),
288       command_line_(command_line) {}
289 
~ChromeRestartRequest()290 ChromeRestartRequest::~ChromeRestartRequest() {}
291 
Start()292 void ChromeRestartRequest::Start() {
293   VLOG(1) << "Requesting a restart with PID " << pid_
294           << " and command line: " << command_line_;
295 
296   // Session Manager may kill the chrome anytime after this point.
297   // Write exit_cleanly and other stuff to the disk here.
298   g_browser_process->EndSession();
299 
300   PrefService* local_state = g_browser_process->local_state();
301   if (!local_state) {
302     RestartJob();
303     return;
304   }
305 
306   // XXX: normally this call must not be needed, however RestartJob
307   // just kills us so settings may be lost. See http://crosbug.com/13102
308   local_state->CommitPendingWrite();
309   timer_.Start(
310       FROM_HERE, base::TimeDelta::FromSeconds(3), this,
311       &ChromeRestartRequest::RestartJob);
312 
313   // Post a task to local state task runner thus it occurs last on the task
314   // queue, so it would be executed after committing pending write on that
315   // thread.
316   scoped_refptr<base::SequencedTaskRunner> local_state_task_runner =
317       JsonPrefStore::GetTaskRunnerForFile(
318           base::FilePath(chrome::kLocalStorePoolName),
319           BrowserThread::GetBlockingPool());
320   local_state_task_runner->PostTaskAndReply(
321       FROM_HERE,
322       base::Bind(&EnsureLocalStateIsWritten),
323       base::Bind(&ChromeRestartRequest::RestartJob, AsWeakPtr()));
324 }
325 
RestartJob()326 void ChromeRestartRequest::RestartJob() {
327   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
328 
329   DBusThreadManager::Get()->GetSessionManagerClient()->RestartJob(
330       pid_, command_line_);
331 
332   delete this;
333 }
334 
335 }  // namespace
336 
GetOffTheRecordCommandLine(const GURL & start_url,bool is_oobe_completed,const CommandLine & base_command_line,CommandLine * command_line)337 std::string GetOffTheRecordCommandLine(
338     const GURL& start_url,
339     bool is_oobe_completed,
340     const CommandLine& base_command_line,
341     CommandLine* command_line) {
342   base::DictionaryValue otr_switches;
343   otr_switches.SetString(switches::kGuestSession, std::string());
344   otr_switches.SetString(::switches::kIncognito, std::string());
345   otr_switches.SetString(::switches::kLoggingLevel, kGuestModeLoggingLevel);
346   otr_switches.SetString(switches::kLoginUser, UserManager::kGuestUserName);
347 
348   // Override the home page.
349   otr_switches.SetString(::switches::kHomePage,
350                          GURL(chrome::kChromeUINewTabURL).spec());
351 
352   // If OOBE is not finished yet, lock down the guest session to not allow
353   // surfing the web. Guest mode is still useful to inspect logs and run network
354   // diagnostics.
355   if (!is_oobe_completed)
356     otr_switches.SetString(switches::kOobeGuestSession, std::string());
357 
358   return DeriveCommandLine(start_url,
359                            base_command_line,
360                            otr_switches,
361                            command_line);
362 }
363 
RestartChrome(const std::string & command_line)364 void RestartChrome(const std::string& command_line) {
365   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
366   BootTimesLoader::Get()->set_restart_requested();
367 
368   static bool restart_requested = false;
369   if (restart_requested) {
370     NOTREACHED() << "Request chrome restart for more than once.";
371   }
372   restart_requested = true;
373 
374   if (!base::SysInfo::IsRunningOnChromeOS()) {
375     // Relaunch chrome without session manager on dev box.
376     ReLaunch(command_line);
377     return;
378   }
379 
380   // ChromeRestartRequest deletes itself after request sent to session manager.
381   (new ChromeRestartRequest(command_line))->Start();
382 }
383 
384 }  // namespace chromeos
385