Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: chrome/browser/ui/browser_init.cc

Issue 10383114: Rename BrowserInit to StartupBrowserCreator, and move into startup subdir. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/browser_init.h ('k') | chrome/browser/ui/browser_init_browsertest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/ui/browser_init.h"
6
7 #include <algorithm> // For max().
8 #include <set>
9
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/compiler_specific.h"
13 #include "base/environment.h"
14 #include "base/event_recorder.h"
15 #include "base/file_path.h"
16 #include "base/lazy_instance.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/metrics/histogram.h"
19 #include "base/path_service.h"
20 #include "base/string_number_conversions.h"
21 #include "base/string_split.h"
22 #include "base/threading/thread_restrictions.h"
23 #include "base/utf_string_conversions.h"
24 #include "chrome/browser/auto_launch_trial.h"
25 #include "chrome/browser/automation/automation_provider.h"
26 #include "chrome/browser/automation/automation_provider_list.h"
27 #include "chrome/browser/automation/chrome_frame_automation_provider.h"
28 #include "chrome/browser/automation/testing_automation_provider.h"
29 #include "chrome/browser/browser_process.h"
30 #include "chrome/browser/component_updater/component_updater_service.h"
31 #include "chrome/browser/component_updater/flash_component_installer.h"
32 #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
33 #include "chrome/browser/component_updater/recovery_component_installer.h"
34 #include "chrome/browser/component_updater/swiftshader_component_installer.h"
35 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
36 #include "chrome/browser/defaults.h"
37 #include "chrome/browser/extensions/extension_creator.h"
38 #include "chrome/browser/extensions/extension_service.h"
39 #include "chrome/browser/extensions/pack_extension_job.h"
40 #include "chrome/browser/first_run/first_run.h"
41 #include "chrome/browser/google/google_util.h"
42 #include "chrome/browser/infobars/infobar_tab_helper.h"
43 #include "chrome/browser/net/crl_set_fetcher.h"
44 #include "chrome/browser/net/predictor.h"
45 #include "chrome/browser/net/url_fixer_upper.h"
46 #include "chrome/browser/notifications/desktop_notification_service.h"
47 #include "chrome/browser/prefs/incognito_mode_prefs.h"
48 #include "chrome/browser/prefs/pref_service.h"
49 #include "chrome/browser/prefs/session_startup_pref.h"
50 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
51 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory. h"
52 #include "chrome/browser/printing/print_dialog_cloud.h"
53 #include "chrome/browser/profiles/profile.h"
54 #include "chrome/browser/profiles/profile_io_data.h"
55 #include "chrome/browser/profiles/profile_manager.h"
56 #include "chrome/browser/protector/base_setting_change.h"
57 #include "chrome/browser/protector/protected_prefs_watcher.h"
58 #include "chrome/browser/protector/protector_service.h"
59 #include "chrome/browser/protector/protector_service_factory.h"
60 #include "chrome/browser/protector/protector_utils.h"
61 #include "chrome/browser/search_engines/template_url.h"
62 #include "chrome/browser/search_engines/template_url_service.h"
63 #include "chrome/browser/search_engines/template_url_service_factory.h"
64 #include "chrome/browser/sessions/session_restore.h"
65 #include "chrome/browser/sessions/session_service.h"
66 #include "chrome/browser/sessions/session_service_factory.h"
67 #include "chrome/browser/shell_integration.h"
68 #include "chrome/browser/tab_contents/link_infobar_delegate.h"
69 #include "chrome/browser/tabs/pinned_tab_codec.h"
70 #include "chrome/browser/tabs/tab_strip_model.h"
71 #include "chrome/browser/ui/browser_list.h"
72 #include "chrome/browser/ui/browser_navigator.h"
73 #include "chrome/browser/ui/browser_window.h"
74 #include "chrome/browser/ui/startup/autolaunch_prompt.h"
75 #include "chrome/browser/ui/startup/bad_flags_prompt.h"
76 #include "chrome/browser/ui/startup/default_browser_prompt.h"
77 #include "chrome/browser/ui/startup/obsolete_os_prompt.h"
78 #include "chrome/browser/ui/startup/session_crashed_prompt.h"
79 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
80 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
81 #include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
82 #include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
83 #include "chrome/common/chrome_constants.h"
84 #include "chrome/common/chrome_notification_types.h"
85 #include "chrome/common/chrome_paths.h"
86 #include "chrome/common/chrome_result_codes.h"
87 #include "chrome/common/chrome_switches.h"
88 #include "chrome/common/chrome_version_info.h"
89 #include "chrome/common/extensions/extension_constants.h"
90 #include "chrome/common/pref_names.h"
91 #include "chrome/common/url_constants.h"
92 #include "chrome/installer/util/browser_distribution.h"
93 #include "content/public/browser/browser_thread.h"
94 #include "content/public/browser/child_process_security_policy.h"
95 #include "content/public/browser/web_contents.h"
96 #include "content/public/browser/web_contents_view.h"
97 #include "grit/locale_settings.h"
98 #include "net/base/net_util.h"
99 #include "ui/base/l10n/l10n_util.h"
100 #include "ui/base/resource/resource_bundle.h"
101
102 #if defined(OS_CHROMEOS)
103 #include "chrome/browser/chromeos/profile_startup.h"
104 #endif
105
106 #if defined(OS_MACOSX)
107 #include "base/mac/mac_util.h"
108 #include "chrome/browser/ui/cocoa/keystone_infobar_delegate.h"
109 #endif
110
111 #if defined(TOOLKIT_GTK)
112 #include "chrome/browser/ui/gtk/gtk_util.h"
113 #endif
114
115 #if defined(TOOLKIT_VIEWS) && defined(OS_LINUX)
116 #include "ui/base/touch/touch_factory.h"
117 #endif
118
119 #if defined(OS_WIN)
120 #include "base/win/windows_version.h"
121 #include "chrome/browser/ui/browser_init_win.h"
122 #endif
123
124 using content::BrowserThread;
125 using content::ChildProcessSecurityPolicy;
126 using content::WebContents;
127 using protector::BaseSettingChange;
128 using protector::ProtectedPrefsWatcher;
129 using protector::ProtectorService;
130 using protector::ProtectorServiceFactory;
131
132 namespace {
133
134 bool in_synchronous_profile_launch = false;
135
136 // Utility functions ----------------------------------------------------------
137
138 enum LaunchMode {
139 LM_TO_BE_DECIDED = 0, // Possibly direct launch or via a shortcut.
140 LM_AS_WEBAPP, // Launched as a installed web application.
141 LM_WITH_URLS, // Launched with urls in the cmd line.
142 LM_SHORTCUT_NONE, // Not launched from a shortcut.
143 LM_SHORTCUT_NONAME, // Launched from shortcut but no name available.
144 LM_SHORTCUT_UNKNOWN, // Launched from user-defined shortcut.
145 LM_SHORTCUT_QUICKLAUNCH, // Launched from the quick launch bar.
146 LM_SHORTCUT_DESKTOP, // Launched from a desktop shortcut.
147 LM_SHORTCUT_TASKBAR, // Launched from the taskbar.
148 LM_LINUX_MAC_BEOS // Other OS buckets start here.
149 };
150
151 #if defined(OS_WIN)
152 // Undocumented flag in the startup info structure tells us what shortcut was
153 // used to launch the browser. See http://www.catch22.net/tuts/undoc01 for
154 // more information. Confirmed to work on XP, Vista and Win7.
155 LaunchMode GetLaunchShortcutKind() {
156 STARTUPINFOW si = { sizeof(si) };
157 GetStartupInfoW(&si);
158 if (si.dwFlags & 0x800) {
159 if (!si.lpTitle)
160 return LM_SHORTCUT_NONAME;
161 string16 shortcut(si.lpTitle);
162 // The windows quick launch path is not localized.
163 if (shortcut.find(L"\\Quick Launch\\") != string16::npos) {
164 if (base::win::GetVersion() >= base::win::VERSION_WIN7)
165 return LM_SHORTCUT_TASKBAR;
166 else
167 return LM_SHORTCUT_QUICKLAUNCH;
168 }
169 scoped_ptr<base::Environment> env(base::Environment::Create());
170 std::string appdata_path;
171 env->GetVar("USERPROFILE", &appdata_path);
172 if (!appdata_path.empty() &&
173 shortcut.find(ASCIIToWide(appdata_path)) != std::wstring::npos)
174 return LM_SHORTCUT_DESKTOP;
175 return LM_SHORTCUT_UNKNOWN;
176 }
177 return LM_SHORTCUT_NONE;
178 }
179 #else
180 // TODO(cpu): Port to other platforms.
181 LaunchMode GetLaunchShortcutKind() {
182 return LM_LINUX_MAC_BEOS;
183 }
184 #endif
185
186 // Log in a histogram the frequency of launching by the different methods. See
187 // LaunchMode enum for the actual values of the buckets.
188 void RecordLaunchModeHistogram(LaunchMode mode) {
189 int bucket = (mode == LM_TO_BE_DECIDED) ? GetLaunchShortcutKind() : mode;
190 UMA_HISTOGRAM_COUNTS_100("Launch.Modes", bucket);
191 }
192
193 GURL GetWelcomePageURL() {
194 std::string welcome_url = l10n_util::GetStringUTF8(IDS_WELCOME_PAGE_URL);
195 return GURL(welcome_url);
196 }
197
198 void UrlsToTabs(const std::vector<GURL>& urls,
199 std::vector<BrowserInit::LaunchWithProfile::Tab>* tabs) {
200 for (size_t i = 0; i < urls.size(); ++i) {
201 BrowserInit::LaunchWithProfile::Tab tab;
202 tab.is_pinned = false;
203 tab.url = urls[i];
204 tabs->push_back(tab);
205 }
206 }
207
208 // Return true if the command line option --app-id is used. Set
209 // |out_extension| to the app to open, and |out_launch_container|
210 // to the type of window into which the app should be open.
211 bool GetAppLaunchContainer(
212 Profile* profile,
213 const std::string& app_id,
214 const Extension** out_extension,
215 extension_misc::LaunchContainer* out_launch_container) {
216
217 ExtensionService* extensions_service = profile->GetExtensionService();
218 const Extension* extension =
219 extensions_service->GetExtensionById(app_id, false);
220
221 // The extension with id |app_id| may have been uninstalled.
222 if (!extension)
223 return false;
224
225 // Look at preferences to find the right launch container. If no
226 // preference is set, launch as a window.
227 extension_misc::LaunchContainer launch_container =
228 extensions_service->extension_prefs()->GetLaunchContainer(
229 extension, ExtensionPrefs::LAUNCH_WINDOW);
230
231 *out_extension = extension;
232 *out_launch_container = launch_container;
233 return true;
234 }
235
236 void RecordCmdLineAppHistogram() {
237 AppLauncherHandler::RecordAppLaunchType(
238 extension_misc::APP_LAUNCH_CMD_LINE_APP);
239 }
240
241 void RecordAppLaunches(
242 Profile* profile,
243 const std::vector<GURL>& cmd_line_urls,
244 const std::vector<BrowserInit::LaunchWithProfile::Tab>& autolaunch_tabs) {
245 ExtensionService* extension_service = profile->GetExtensionService();
246 DCHECK(extension_service);
247 for (size_t i = 0; i < cmd_line_urls.size(); ++i) {
248 if (extension_service->IsInstalledApp(cmd_line_urls.at(i))) {
249 AppLauncherHandler::RecordAppLaunchType(
250 extension_misc::APP_LAUNCH_CMD_LINE_URL);
251 }
252 }
253 for (size_t i = 0; i < autolaunch_tabs.size(); ++i) {
254 if (extension_service->IsInstalledApp(autolaunch_tabs.at(i).url)) {
255 AppLauncherHandler::RecordAppLaunchType(
256 extension_misc::APP_LAUNCH_AUTOLAUNCH);
257 }
258 }
259 }
260
261 void RegisterComponentsForUpdate(const CommandLine& command_line) {
262 ComponentUpdateService* cus = g_browser_process->component_updater();
263 if (!cus)
264 return;
265 // Registration can be before of after cus->Start() so it is ok to post
266 // a task to the UI thread to do registration once you done the necessary
267 // file IO to know you existing component version.
268 RegisterRecoveryComponent(cus, g_browser_process->local_state());
269 RegisterPepperFlashComponent(cus);
270 RegisterNPAPIFlashComponent(cus);
271 RegisterSwiftShaderComponent(cus);
272
273 // CRLSetFetcher attempts to load a CRL set from either the local disk or
274 // network.
275 if (!command_line.HasSwitch(switches::kDisableCRLSets))
276 g_browser_process->crl_set_fetcher()->StartInitialLoad(cus);
277
278 // This developer version of Pnacl should only be installed for developers.
279 if (command_line.HasSwitch(switches::kEnablePnacl)) {
280 RegisterPnaclComponent(cus);
281 }
282
283 cus->Start();
284 }
285
286 // Keeps track on which profiles have been launched.
287 class ProfileLaunchObserver : public content::NotificationObserver {
288 public:
289 ProfileLaunchObserver() {
290 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
291 content::NotificationService::AllSources());
292 }
293 virtual ~ProfileLaunchObserver() {}
294
295 virtual void Observe(int type,
296 const content::NotificationSource& source,
297 const content::NotificationDetails& details) OVERRIDE {
298 switch (type) {
299 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
300 Profile* profile = content::Source<Profile>(source).ptr();
301 launched_profiles.erase(profile);
302 break;
303 }
304 default:
305 NOTREACHED();
306 }
307 }
308
309 bool HasBeenLaunched(const Profile* profile) {
310 return launched_profiles.find(profile) != launched_profiles.end();
311 }
312
313 void AddLaunched(const Profile* profile) {
314 launched_profiles.insert(profile);
315 }
316
317 private:
318 std::set<const Profile*> launched_profiles;
319 content::NotificationRegistrar registrar_;
320
321 DISALLOW_COPY_AND_ASSIGN(ProfileLaunchObserver);
322 };
323
324 base::LazyInstance<ProfileLaunchObserver> profile_launch_observer =
325 LAZY_INSTANCE_INITIALIZER;
326
327 // Returns true if |profile| has exited uncleanly and has not been launched
328 // after the unclean exit.
329 bool HasPendingUncleanExit(Profile* profile) {
330 return !profile->DidLastSessionExitCleanly() &&
331 !profile_launch_observer.Get().HasBeenLaunched(profile);
332 }
333
334 } // namespace
335
336
337 // BrowserInit ----------------------------------------------------------------
338
339 BrowserInit::BrowserInit() {}
340
341 BrowserInit::~BrowserInit() {}
342
343 // static
344 bool BrowserInit::was_restarted_read_ = false;
345
346 void BrowserInit::AddFirstRunTab(const GURL& url) {
347 first_run_tabs_.push_back(url);
348 }
349
350 // static
351 bool BrowserInit::InSynchronousProfileLaunch() {
352 return in_synchronous_profile_launch;
353 }
354
355 bool BrowserInit::LaunchBrowser(const CommandLine& command_line,
356 Profile* profile,
357 const FilePath& cur_dir,
358 IsProcessStartup process_startup,
359 IsFirstRun is_first_run,
360 int* return_code) {
361 in_synchronous_profile_launch = process_startup == IS_PROCESS_STARTUP;
362 DCHECK(profile);
363
364 // Continue with the incognito profile from here on if Incognito mode
365 // is forced.
366 if (IncognitoModePrefs::ShouldLaunchIncognito(command_line,
367 profile->GetPrefs())) {
368 profile = profile->GetOffTheRecordProfile();
369 } else if (command_line.HasSwitch(switches::kIncognito)) {
370 LOG(WARNING) << "Incognito mode disabled by policy, launching a normal "
371 << "browser session.";
372 }
373
374 BrowserInit::LaunchWithProfile lwp(cur_dir, command_line, this, is_first_run);
375 std::vector<GURL> urls_to_launch = BrowserInit::GetURLsFromCommandLine(
376 command_line, cur_dir, profile);
377 bool launched = lwp.Launch(profile, urls_to_launch,
378 in_synchronous_profile_launch);
379 in_synchronous_profile_launch = false;
380
381 if (!launched) {
382 LOG(ERROR) << "launch error";
383 if (return_code)
384 *return_code = chrome::RESULT_CODE_INVALID_CMDLINE_URL;
385 return false;
386 }
387 profile_launch_observer.Get().AddLaunched(profile);
388
389 #if defined(OS_CHROMEOS)
390 chromeos::ProfileStartup(profile, process_startup);
391 #endif
392 return true;
393 }
394
395 // static
396 bool BrowserInit::WasRestarted() {
397 // Stores the value of the preference kWasRestarted had when it was read.
398 static bool was_restarted = false;
399
400 if (!was_restarted_read_) {
401 PrefService* pref_service = g_browser_process->local_state();
402 was_restarted = pref_service->GetBoolean(prefs::kWasRestarted);
403 pref_service->SetBoolean(prefs::kWasRestarted, false);
404 was_restarted_read_ = true;
405 }
406 return was_restarted;
407 }
408
409 // static
410 SessionStartupPref BrowserInit::GetSessionStartupPref(
411 const CommandLine& command_line,
412 Profile* profile) {
413 SessionStartupPref pref = SessionStartupPref::GetStartupPref(profile);
414
415 // Session restore should be avoided on the first run.
416 if (first_run::IsChromeFirstRun())
417 pref.type = SessionStartupPref::DEFAULT;
418
419 if (command_line.HasSwitch(switches::kRestoreLastSession) ||
420 BrowserInit::WasRestarted()) {
421 pref.type = SessionStartupPref::LAST;
422 }
423 if (pref.type == SessionStartupPref::LAST &&
424 IncognitoModePrefs::ShouldLaunchIncognito(command_line,
425 profile->GetPrefs())) {
426 // We don't store session information when incognito. If the user has
427 // chosen to restore last session and launched incognito, fallback to
428 // default launch behavior.
429 pref.type = SessionStartupPref::DEFAULT;
430 }
431 return pref;
432 }
433
434
435 // BrowserInit::LaunchWithProfile::Tab ----------------------------------------
436
437 BrowserInit::LaunchWithProfile::Tab::Tab() : is_app(false), is_pinned(true) {}
438
439 BrowserInit::LaunchWithProfile::Tab::~Tab() {}
440
441
442 // BrowserInit::LaunchWithProfile ---------------------------------------------
443
444 BrowserInit::LaunchWithProfile::LaunchWithProfile(
445 const FilePath& cur_dir,
446 const CommandLine& command_line,
447 IsFirstRun is_first_run)
448 : cur_dir_(cur_dir),
449 command_line_(command_line),
450 profile_(NULL),
451 browser_init_(NULL),
452 is_first_run_(is_first_run == IS_FIRST_RUN) {
453 }
454
455 BrowserInit::LaunchWithProfile::LaunchWithProfile(
456 const FilePath& cur_dir,
457 const CommandLine& command_line,
458 BrowserInit* browser_init,
459 IsFirstRun is_first_run)
460 : cur_dir_(cur_dir),
461 command_line_(command_line),
462 profile_(NULL),
463 browser_init_(browser_init),
464 is_first_run_(is_first_run == IS_FIRST_RUN) {
465 }
466
467 BrowserInit::LaunchWithProfile::~LaunchWithProfile() {
468 }
469
470 bool BrowserInit::LaunchWithProfile::Launch(
471 Profile* profile,
472 const std::vector<GURL>& urls_to_open,
473 bool process_startup) {
474 DCHECK(profile);
475 profile_ = profile;
476
477 if (command_line_.HasSwitch(switches::kDnsLogDetails))
478 chrome_browser_net::EnablePredictorDetailedLog(true);
479 if (command_line_.HasSwitch(switches::kDnsPrefetchDisable) &&
480 profile->GetNetworkPredictor()) {
481 profile->GetNetworkPredictor()->EnablePredictor(false);
482 }
483
484 if (command_line_.HasSwitch(switches::kDumpHistogramsOnExit))
485 base::StatisticsRecorder::set_dump_on_exit(true);
486
487 if (command_line_.HasSwitch(switches::kRemoteDebuggingPort)) {
488 std::string port_str =
489 command_line_.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
490 int64 port;
491 if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535) {
492 std::string frontend_str;
493 if (command_line_.HasSwitch(switches::kRemoteDebuggingFrontend)) {
494 frontend_str = command_line_.GetSwitchValueASCII(
495 switches::kRemoteDebuggingFrontend);
496 }
497 g_browser_process->InitDevToolsHttpProtocolHandler(
498 profile,
499 "127.0.0.1",
500 static_cast<int>(port),
501 frontend_str);
502 } else {
503 DLOG(WARNING) << "Invalid http debugger port number " << port;
504 }
505 }
506
507 // Open the required browser windows and tabs. First, see if
508 // we're being run as an application window. If so, the user
509 // opened an app shortcut. Don't restore tabs or open initial
510 // URLs in that case. The user should see the window as an app,
511 // not as chrome.
512 // Special case is when app switches are passed but we do want to restore
513 // session. In that case open app window + focus it after session is restored.
514 if (OpenApplicationWindow(profile) && !browser_defaults::kAppRestoreSession) {
515 RecordLaunchModeHistogram(LM_AS_WEBAPP);
516 } else {
517 Browser* browser_to_focus = NULL;
518 // In case of app mode + session restore we want to focus that app.
519 if (browser_defaults::kAppRestoreSession)
520 browser_to_focus = BrowserList::GetLastActive();
521
522 RecordLaunchModeHistogram(urls_to_open.empty()?
523 LM_TO_BE_DECIDED : LM_WITH_URLS);
524
525 // Notify user if the Preferences backup is invalid or changes to settings
526 // affecting browser startup have been detected.
527 CheckPreferencesBackup(profile);
528
529 ProcessLaunchURLs(process_startup, urls_to_open);
530
531 // If this is an app launch, but we didn't open an app window, it may
532 // be an app tab.
533 OpenApplicationTab(profile);
534
535 if (browser_to_focus)
536 browser_to_focus->GetSelectedWebContents()->GetView()->SetInitialFocus();
537
538 if (process_startup) {
539 if (browser_defaults::kOSSupportsOtherBrowsers &&
540 !command_line_.HasSwitch(switches::kNoDefaultBrowserCheck)) {
541 if (!browser::ShowAutolaunchPrompt(profile))
542 browser::ShowDefaultBrowserPrompt(profile);
543 }
544 #if defined(OS_MACOSX)
545 // Check whether the auto-update system needs to be promoted from user
546 // to system.
547 KeystoneInfoBar::PromotionInfoBar(profile);
548 #endif
549 }
550 }
551
552 #if defined(OS_WIN)
553 // Print the selected page if the command line switch exists. Note that the
554 // current selected tab would be the page which will be printed.
555 if (command_line_.HasSwitch(switches::kPrint)) {
556 Browser* browser = BrowserList::GetLastActive();
557 browser->Print();
558 }
559 #endif
560
561 // If we're recording or playing back, startup the EventRecorder now
562 // unless otherwise specified.
563 if (!command_line_.HasSwitch(switches::kNoEvents)) {
564 FilePath script_path;
565 PathService::Get(chrome::FILE_RECORDED_SCRIPT, &script_path);
566
567 bool record_mode = command_line_.HasSwitch(switches::kRecordMode);
568 bool playback_mode = command_line_.HasSwitch(switches::kPlaybackMode);
569
570 if (record_mode && chrome::kRecordModeEnabled)
571 base::EventRecorder::current()->StartRecording(script_path);
572 if (playback_mode)
573 base::EventRecorder::current()->StartPlayback(script_path);
574 }
575
576 #if defined(OS_WIN)
577 if (process_startup)
578 ShellIntegration::MigrateChromiumShortcuts();
579 #endif // defined(OS_WIN)
580
581 return true;
582 }
583
584 bool BrowserInit::LaunchWithProfile::IsAppLaunch(std::string* app_url,
585 std::string* app_id) {
586 if (command_line_.HasSwitch(switches::kApp)) {
587 if (app_url)
588 *app_url = command_line_.GetSwitchValueASCII(switches::kApp);
589 return true;
590 }
591 if (command_line_.HasSwitch(switches::kAppId)) {
592 if (app_id)
593 *app_id = command_line_.GetSwitchValueASCII(switches::kAppId);
594 return true;
595 }
596 return false;
597 }
598
599 bool BrowserInit::LaunchWithProfile::OpenApplicationTab(Profile* profile) {
600 std::string app_id;
601 // App shortcuts to URLs always open in an app window. Because this
602 // function will open an app that should be in a tab, there is no need
603 // to look at the app URL. OpenApplicationWindow() will open app url
604 // shortcuts.
605 if (!IsAppLaunch(NULL, &app_id) || app_id.empty())
606 return false;
607
608 extension_misc::LaunchContainer launch_container;
609 const Extension* extension;
610 if (!GetAppLaunchContainer(profile, app_id, &extension, &launch_container))
611 return false;
612
613 // If the user doesn't want to open a tab, fail.
614 if (launch_container != extension_misc::LAUNCH_TAB)
615 return false;
616
617 RecordCmdLineAppHistogram();
618
619 WebContents* app_tab = Browser::OpenApplicationTab(profile, extension, GURL(),
620 NEW_FOREGROUND_TAB);
621 return (app_tab != NULL);
622 }
623
624 bool BrowserInit::LaunchWithProfile::OpenApplicationWindow(Profile* profile) {
625 std::string url_string, app_id;
626 if (!IsAppLaunch(&url_string, &app_id))
627 return false;
628
629 // This can fail if the app_id is invalid. It can also fail if the
630 // extension is external, and has not yet been installed.
631 // TODO(skerner): Do something reasonable here. Pop up a warning panel?
632 // Open an URL to the gallery page of the extension id?
633 if (!app_id.empty()) {
634 extension_misc::LaunchContainer launch_container;
635 const Extension* extension;
636 if (!GetAppLaunchContainer(profile, app_id, &extension, &launch_container))
637 return false;
638
639 // TODO(skerner): Could pass in |extension| and |launch_container|,
640 // and avoid calling GetAppLaunchContainer() both here and in
641 // OpenApplicationTab().
642
643 if (launch_container == extension_misc::LAUNCH_TAB)
644 return false;
645
646 RecordCmdLineAppHistogram();
647 WebContents* tab_in_app_window = Browser::OpenApplication(
648 profile, extension, launch_container, GURL(), NEW_WINDOW);
649 // Platform apps fire off a launch event which may or may not open a window.
650 return (tab_in_app_window != NULL || extension->is_platform_app());
651 }
652
653 if (url_string.empty())
654 return false;
655
656 #if defined(OS_WIN) // Fix up Windows shortcuts.
657 ReplaceSubstringsAfterOffset(&url_string, 0, "\\x", "%");
658 #endif
659 GURL url(url_string);
660
661 // Restrict allowed URLs for --app switch.
662 if (!url.is_empty() && url.is_valid()) {
663 ChildProcessSecurityPolicy *policy =
664 ChildProcessSecurityPolicy::GetInstance();
665 if (policy->IsWebSafeScheme(url.scheme()) ||
666 url.SchemeIs(chrome::kFileScheme)) {
667
668 if (profile->GetExtensionService()->IsInstalledApp(url)) {
669 RecordCmdLineAppHistogram();
670 } else {
671 AppLauncherHandler::RecordAppLaunchType(
672 extension_misc::APP_LAUNCH_CMD_LINE_APP_LEGACY);
673 }
674 WebContents* app_tab = Browser::OpenAppShortcutWindow(
675 profile,
676 url,
677 true); // Update app info.
678 return (app_tab != NULL);
679 }
680 }
681 return false;
682 }
683
684 void BrowserInit::LaunchWithProfile::ProcessLaunchURLs(
685 bool process_startup,
686 const std::vector<GURL>& urls_to_open) {
687 // If we're starting up in "background mode" (no open browser window) then
688 // don't open any browser windows, unless kAutoLaunchAtStartup is also
689 // specified.
690 if (process_startup &&
691 command_line_.HasSwitch(switches::kNoStartupWindow) &&
692 !command_line_.HasSwitch(switches::kAutoLaunchAtStartup)) {
693 return;
694 }
695
696 if (process_startup && ProcessStartupURLs(urls_to_open)) {
697 // ProcessStartupURLs processed the urls, nothing else to do.
698 return;
699 }
700
701 IsProcessStartup is_process_startup = process_startup ?
702 IS_PROCESS_STARTUP : IS_NOT_PROCESS_STARTUP;
703 if (!process_startup) {
704 // Even if we're not starting a new process, this may conceptually be
705 // "startup" for the user and so should be handled in a similar way. Eg.,
706 // Chrome may have been running in the background due to an app with a
707 // background page being installed, or running with only an app window
708 // displayed.
709 SessionService* service = SessionServiceFactory::GetForProfile(profile_);
710 if (service && service->ShouldNewWindowStartSession()) {
711 // Restore the last session if any.
712 if (!HasPendingUncleanExit(profile_) &&
713 service->RestoreIfNecessary(urls_to_open)) {
714 return;
715 }
716 // Open user-specified URLs like pinned tabs and startup tabs.
717 Browser* browser = ProcessSpecifiedURLs(urls_to_open);
718 if (browser) {
719 AddInfoBarsIfNecessary(browser, is_process_startup);
720 return;
721 }
722 }
723 }
724
725 // Session startup didn't occur, open the urls.
726
727 Browser* browser = NULL;
728 std::vector<GURL> adjust_urls = urls_to_open;
729 if (adjust_urls.empty())
730 AddStartupURLs(&adjust_urls);
731 else if (!command_line_.HasSwitch(switches::kOpenInNewWindow))
732 browser = BrowserList::GetLastActiveWithProfile(profile_);
733
734 // This will launch a browser; prevent session restore.
735 in_synchronous_profile_launch = true;
736 browser = OpenURLsInBrowser(browser, process_startup, adjust_urls);
737 in_synchronous_profile_launch = false;
738 AddInfoBarsIfNecessary(browser, is_process_startup);
739 }
740
741 bool BrowserInit::LaunchWithProfile::ProcessStartupURLs(
742 const std::vector<GURL>& urls_to_open) {
743 SessionStartupPref pref = GetSessionStartupPref(command_line_, profile_);
744
745 if (pref.type == SessionStartupPref::LAST) {
746 if (!profile_->DidLastSessionExitCleanly() &&
747 !command_line_.HasSwitch(switches::kRestoreLastSession)) {
748 // The last session crashed. It's possible automatically loading the
749 // page will trigger another crash, locking the user out of chrome.
750 // To avoid this, don't restore on startup but instead show the crashed
751 // infobar.
752 return false;
753 }
754
755 uint32 restore_behavior = SessionRestore::SYNCHRONOUS |
756 SessionRestore::ALWAYS_CREATE_TABBED_BROWSER;
757 #if defined(OS_MACOSX)
758 // On Mac, when restoring a session with no windows, suppress the creation
759 // of a new window in the case where the system is launching Chrome via a
760 // login item or Lion's resume feature.
761 if (base::mac::WasLaunchedAsLoginOrResumeItem()) {
762 restore_behavior = restore_behavior &
763 ~SessionRestore::ALWAYS_CREATE_TABBED_BROWSER;
764 }
765 #endif
766
767 Browser* browser = SessionRestore::RestoreSession(profile_,
768 NULL,
769 restore_behavior,
770 urls_to_open);
771 AddInfoBarsIfNecessary(browser, IS_PROCESS_STARTUP);
772 return true;
773 }
774
775 Browser* browser = ProcessSpecifiedURLs(urls_to_open);
776 if (!browser)
777 return false;
778
779 AddInfoBarsIfNecessary(browser, IS_PROCESS_STARTUP);
780 return true;
781 }
782
783 Browser* BrowserInit::LaunchWithProfile::ProcessSpecifiedURLs(
784 const std::vector<GURL>& urls_to_open) {
785 SessionStartupPref pref = GetSessionStartupPref(command_line_, profile_);
786 std::vector<Tab> tabs;
787 // Pinned tabs should not be displayed when chrome is launched in incognito
788 // mode. Also, no pages should be opened automatically if the session
789 // crashed. Otherwise it might trigger another crash, locking the user out of
790 // chrome. The crash infobar is shown in this case.
791 if (!IncognitoModePrefs::ShouldLaunchIncognito(command_line_,
792 profile_->GetPrefs()) &&
793 !HasPendingUncleanExit(profile_)) {
794 tabs = PinnedTabCodec::ReadPinnedTabs(profile_);
795 }
796
797 RecordAppLaunches(profile_, urls_to_open, tabs);
798
799 if (!urls_to_open.empty()) {
800 // If urls were specified on the command line, use them.
801 UrlsToTabs(urls_to_open, &tabs);
802 } else if (pref.type == SessionStartupPref::URLS && !pref.urls.empty() &&
803 !HasPendingUncleanExit(profile_)) {
804 // Only use the set of urls specified in preferences if nothing was
805 // specified on the command line. Filter out any urls that are to be
806 // restored by virtue of having been previously pinned.
807 AddUniqueURLs(pref.urls, &tabs);
808 } else if (pref.type == SessionStartupPref::DEFAULT) {
809 std::vector<GURL> urls;
810 AddStartupURLs(&urls);
811 UrlsToTabs(urls, &tabs);
812
813 } else if (pref.type == SessionStartupPref::HOMEPAGE) {
814 // If 'homepage' selected, either by the user or by a policy, we should
815 // have migrated them to another value.
816 NOTREACHED() << "SessionStartupPref has deprecated type HOMEPAGE";
817 }
818
819 if (tabs.empty())
820 return NULL;
821
822 Browser* browser = OpenTabsInBrowser(NULL, true, tabs);
823 return browser;
824 }
825
826 void BrowserInit::LaunchWithProfile::AddUniqueURLs(
827 const std::vector<GURL>& urls,
828 std::vector<Tab>* tabs) {
829 size_t num_existing_tabs = tabs->size();
830 for (size_t i = 0; i < urls.size(); ++i) {
831 bool in_tabs = false;
832 for (size_t j = 0; j < num_existing_tabs; ++j) {
833 if (urls[i] == (*tabs)[j].url) {
834 in_tabs = true;
835 break;
836 }
837 }
838 if (!in_tabs) {
839 BrowserInit::LaunchWithProfile::Tab tab;
840 tab.is_pinned = false;
841 tab.url = urls[i];
842 tabs->push_back(tab);
843 }
844 }
845 }
846
847 Browser* BrowserInit::LaunchWithProfile::OpenURLsInBrowser(
848 Browser* browser,
849 bool process_startup,
850 const std::vector<GURL>& urls) {
851 std::vector<Tab> tabs;
852 UrlsToTabs(urls, &tabs);
853 return OpenTabsInBrowser(browser, process_startup, tabs);
854 }
855
856 Browser* BrowserInit::LaunchWithProfile::OpenTabsInBrowser(
857 Browser* browser,
858 bool process_startup,
859 const std::vector<Tab>& tabs) {
860 DCHECK(!tabs.empty());
861
862 // If we don't yet have a profile, try to use the one we're given from
863 // |browser|. While we may not end up actually using |browser| (since it
864 // could be a popup window), we can at least use the profile.
865 if (!profile_ && browser)
866 profile_ = browser->profile();
867
868 if (!browser || !browser->is_type_tabbed()) {
869 browser = Browser::Create(profile_);
870 } else {
871 #if defined(TOOLKIT_GTK)
872 // Setting the time of the last action on the window here allows us to steal
873 // focus, which is what the user wants when opening a new tab in an existing
874 // browser window.
875 gtk_util::SetWMLastUserActionTime(browser->window()->GetNativeHandle());
876 #endif
877 }
878
879 #if !defined(OS_MACOSX)
880 // In kiosk mode, we want to always be fullscreen, so switch to that now.
881 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
882 browser->ToggleFullscreenMode();
883 #endif
884
885 bool first_tab = true;
886 for (size_t i = 0; i < tabs.size(); ++i) {
887 // We skip URLs that we'd have to launch an external protocol handler for.
888 // This avoids us getting into an infinite loop asking ourselves to open
889 // a URL, should the handler be (incorrectly) configured to be us. Anyone
890 // asking us to open such a URL should really ask the handler directly.
891 bool handled_by_chrome = ProfileIOData::IsHandledURL(tabs[i].url) ||
892 (profile_ && profile_->GetProtocolHandlerRegistry()->IsHandledProtocol(
893 tabs[i].url.scheme()));
894 if (!process_startup && !handled_by_chrome)
895 continue;
896
897 int add_types = first_tab ? TabStripModel::ADD_ACTIVE :
898 TabStripModel::ADD_NONE;
899 add_types |= TabStripModel::ADD_FORCE_INDEX;
900 if (tabs[i].is_pinned)
901 add_types |= TabStripModel::ADD_PINNED;
902 int index = browser->GetIndexForInsertionDuringRestore(i);
903
904 browser::NavigateParams params(browser, tabs[i].url,
905 content::PAGE_TRANSITION_START_PAGE);
906 params.disposition = first_tab ? NEW_FOREGROUND_TAB :
907 NEW_BACKGROUND_TAB;
908 params.tabstrip_index = index;
909 params.tabstrip_add_types = add_types;
910 params.extension_app_id = tabs[i].app_id;
911 browser::Navigate(&params);
912
913 first_tab = false;
914 }
915 if (!browser->GetSelectedWebContents()) {
916 // TODO: this is a work around for 110909. Figure out why it's needed.
917 if (!browser->tab_count())
918 browser->AddBlankTab(true);
919 else
920 browser->ActivateTabAt(0, false);
921 }
922
923 browser->window()->Show();
924 // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
925 // focus explicitly.
926 browser->GetSelectedWebContents()->GetView()->SetInitialFocus();
927
928 return browser;
929 }
930
931 void BrowserInit::LaunchWithProfile::AddInfoBarsIfNecessary(
932 Browser* browser,
933 IsProcessStartup is_process_startup) {
934 if (!browser || !profile_ || browser->tab_count() == 0)
935 return;
936
937 if (HasPendingUncleanExit(browser->profile()))
938 browser::ShowSessionCrashedPrompt(browser);
939
940 // The bad flags info bar and the obsolete system info bar are only added to
941 // the first profile which is launched. Other profiles might be restoring the
942 // browsing sessions asynchronously, so we cannot add the info bars to the
943 // focused tabs here.
944 if (is_process_startup == IS_PROCESS_STARTUP) {
945 browser::ShowBadFlagsPrompt(browser);
946 browser::ShowObsoleteOSPrompt(browser);
947 }
948 }
949
950
951 void BrowserInit::LaunchWithProfile::AddStartupURLs(
952 std::vector<GURL>* startup_urls) const {
953 // If we have urls specified beforehand (i.e. from command line) use them
954 // and nothing else.
955 if (!startup_urls->empty())
956 return;
957
958 // If we have urls specified by the first run master preferences use them
959 // and nothing else.
960 if (browser_init_) {
961 if (!browser_init_->first_run_tabs_.empty()) {
962 std::vector<GURL>::iterator it = browser_init_->first_run_tabs_.begin();
963 while (it != browser_init_->first_run_tabs_.end()) {
964 // Replace magic names for the actual urls.
965 if (it->host() == "new_tab_page") {
966 startup_urls->push_back(GURL(chrome::kChromeUINewTabURL));
967 } else if (it->host() == "welcome_page") {
968 startup_urls->push_back(GetWelcomePageURL());
969 } else {
970 startup_urls->push_back(*it);
971 }
972 ++it;
973 }
974 browser_init_->first_run_tabs_.clear();
975 }
976 }
977
978 // Otherwise open at least the new tab page (and the welcome page, if this
979 // is the first time the browser is being started), or the set of URLs
980 // specified on the command line.
981 if (startup_urls->empty()) {
982 startup_urls->push_back(GURL(chrome::kChromeUINewTabURL));
983 PrefService* prefs = g_browser_process->local_state();
984 if (prefs->FindPreference(prefs::kShouldShowWelcomePage) &&
985 prefs->GetBoolean(prefs::kShouldShowWelcomePage)) {
986 // Reset the preference so we don't show the welcome page next time.
987 prefs->ClearPref(prefs::kShouldShowWelcomePage);
988 startup_urls->push_back(GetWelcomePageURL());
989 }
990 }
991
992 // If the sync promo page is going to be displayed then insert it at the front
993 // of the list.
994 if (SyncPromoUI::ShouldShowSyncPromoAtStartup(profile_, is_first_run_)) {
995 SyncPromoUI::DidShowSyncPromoAtStartup(profile_);
996 GURL old_url = (*startup_urls)[0];
997 (*startup_urls)[0] =
998 SyncPromoUI::GetSyncPromoURL(GURL(chrome::kChromeUINewTabURL),
999 SyncPromoUI::SOURCE_START_PAGE);
1000
1001 // An empty URL means to go to the home page.
1002 if (old_url.is_empty() &&
1003 profile_->GetHomePage() == GURL(chrome::kChromeUINewTabURL)) {
1004 old_url = GURL(chrome::kChromeUINewTabURL);
1005 }
1006
1007 // If the old URL is not the NTP then insert it right after the sync promo.
1008 if (old_url != GURL(chrome::kChromeUINewTabURL))
1009 startup_urls->insert(startup_urls->begin() + 1, old_url);
1010
1011 // If we have more than two startup tabs then skip the welcome page.
1012 if (startup_urls->size() > 2) {
1013 std::vector<GURL>::iterator it = std::find(
1014 startup_urls->begin(), startup_urls->end(), GetWelcomePageURL());
1015 if (it != startup_urls->end())
1016 startup_urls->erase(it);
1017 }
1018 }
1019 }
1020
1021 void BrowserInit::LaunchWithProfile::CheckPreferencesBackup(Profile* profile) {
1022 ProtectorService* protector_service =
1023 ProtectorServiceFactory::GetForProfile(profile);
1024 ProtectedPrefsWatcher* prefs_watcher = protector_service->GetPrefsWatcher();
1025
1026 // Check if backup is valid.
1027 if (!prefs_watcher->is_backup_valid()) {
1028 protector_service->ShowChange(protector::CreatePrefsBackupInvalidChange());
1029 // Further checks make no sense.
1030 return;
1031 }
1032
1033 // Check for session startup (including pinned tabs) changes.
1034 if (SessionStartupPref::DidStartupPrefChange(profile) ||
1035 prefs_watcher->DidPrefChange(prefs::kPinnedTabs)) {
1036 LOG(WARNING) << "Session startup settings have changed";
1037 SessionStartupPref new_pref = SessionStartupPref::GetStartupPref(profile);
1038 PinnedTabCodec::Tabs new_tabs = PinnedTabCodec::ReadPinnedTabs(profile);
1039 const base::Value* tabs_backup =
1040 prefs_watcher->GetBackupForPref(prefs::kPinnedTabs);
1041 protector_service->ShowChange(protector::CreateSessionStartupChange(
1042 new_pref,
1043 new_tabs,
1044 SessionStartupPref::GetStartupPrefBackup(profile),
1045 PinnedTabCodec::ReadPinnedTabs(tabs_backup)));
1046 }
1047
1048 // Check for homepage changes.
1049 if (prefs_watcher->DidPrefChange(prefs::kHomePage) ||
1050 prefs_watcher->DidPrefChange(prefs::kHomePageIsNewTabPage) ||
1051 prefs_watcher->DidPrefChange(prefs::kShowHomeButton)) {
1052 LOG(WARNING) << "Homepage has changed";
1053 PrefService* prefs = profile->GetPrefs();
1054 std::string backup_homepage;
1055 bool backup_homepage_is_ntp;
1056 bool backup_show_home_button;
1057 if (!prefs_watcher->GetBackupForPref(prefs::kHomePage)->
1058 GetAsString(&backup_homepage) ||
1059 !prefs_watcher->GetBackupForPref(prefs::kHomePageIsNewTabPage)->
1060 GetAsBoolean(&backup_homepage_is_ntp) ||
1061 !prefs_watcher->GetBackupForPref(prefs::kShowHomeButton)->
1062 GetAsBoolean(&backup_show_home_button)) {
1063 NOTREACHED();
1064 }
1065 protector_service->ShowChange(protector::CreateHomepageChange(
1066 // New:
1067 prefs->GetString(prefs::kHomePage),
1068 prefs->GetBoolean(prefs::kHomePageIsNewTabPage),
1069 prefs->GetBoolean(prefs::kShowHomeButton),
1070 // Backup:
1071 backup_homepage,
1072 backup_homepage_is_ntp,
1073 backup_show_home_button));
1074 }
1075 }
1076
1077 std::vector<GURL> BrowserInit::GetURLsFromCommandLine(
1078 const CommandLine& command_line,
1079 const FilePath& cur_dir,
1080 Profile* profile) {
1081 std::vector<GURL> urls;
1082 const CommandLine::StringVector& params = command_line.GetArgs();
1083
1084 for (size_t i = 0; i < params.size(); ++i) {
1085 FilePath param = FilePath(params[i]);
1086 // Handle Vista way of searching - "? <search-term>"
1087 if (param.value().size() > 2 &&
1088 param.value()[0] == '?' && param.value()[1] == ' ') {
1089 const TemplateURL* default_provider =
1090 TemplateURLServiceFactory::GetForProfile(profile)->
1091 GetDefaultSearchProvider();
1092 if (default_provider) {
1093 const TemplateURLRef& search_url = default_provider->url_ref();
1094 DCHECK(search_url.SupportsReplacement());
1095 string16 search_term = param.LossyDisplayName().substr(2);
1096 urls.push_back(GURL(search_url.ReplaceSearchTerms(search_term,
1097 TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16())));
1098 continue;
1099 }
1100 }
1101
1102 // Otherwise, fall through to treating it as a URL.
1103
1104 // This will create a file URL or a regular URL.
1105 // This call can (in rare circumstances) block the UI thread.
1106 // Allow it until this bug is fixed.
1107 // http://code.google.com/p/chromium/issues/detail?id=60641
1108 GURL url;
1109 {
1110 base::ThreadRestrictions::ScopedAllowIO allow_io;
1111 url = URLFixerUpper::FixupRelativeFile(cur_dir, param);
1112 }
1113 // Exclude dangerous schemes.
1114 if (url.is_valid()) {
1115 ChildProcessSecurityPolicy *policy =
1116 ChildProcessSecurityPolicy::GetInstance();
1117 if (policy->IsWebSafeScheme(url.scheme()) ||
1118 url.SchemeIs(chrome::kFileScheme) ||
1119 #if defined(OS_CHROMEOS)
1120 // In ChromeOS, allow a settings page to be specified on the
1121 // command line. See ExistingUserController::OnLoginSuccess.
1122 (url.spec().find(chrome::kChromeUISettingsURL) == 0) ||
1123 #endif
1124 (url.spec().compare(chrome::kAboutBlankURL) == 0)) {
1125 urls.push_back(url);
1126 }
1127 }
1128 }
1129 #if defined(OS_WIN)
1130 if (urls.empty()) {
1131 // If we are in Windows 8 metro mode and were launched as a result of the
1132 // search charm or via a url navigation in metro, then fetch the
1133 // corresponding url.
1134 GURL url = browser::GetURLToOpen(profile);
1135 if (url.is_valid())
1136 urls.push_back(GURL(url));
1137 }
1138 #endif // OS_WIN
1139 return urls;
1140 }
1141
1142 bool BrowserInit::ProcessCmdLineImpl(
1143 const CommandLine& command_line,
1144 const FilePath& cur_dir,
1145 bool process_startup,
1146 Profile* last_used_profile,
1147 const Profiles& last_opened_profiles,
1148 int* return_code,
1149 BrowserInit* browser_init) {
1150 DCHECK(last_used_profile);
1151 if (process_startup) {
1152 if (command_line.HasSwitch(switches::kDisablePromptOnRepost))
1153 content::NavigationController::DisablePromptOnRepost();
1154 if (!command_line.HasSwitch(switches::kDisableComponentUpdate))
1155 RegisterComponentsForUpdate(command_line);
1156 }
1157
1158 bool silent_launch = false;
1159
1160 #if defined(ENABLE_AUTOMATION)
1161 // Look for the testing channel ID ONLY during process startup
1162 if (process_startup &&
1163 command_line.HasSwitch(switches::kTestingChannelID)) {
1164 std::string testing_channel_id = command_line.GetSwitchValueASCII(
1165 switches::kTestingChannelID);
1166 // TODO(sanjeevr) Check if we need to make this a singleton for
1167 // compatibility with the old testing code
1168 // If there are any extra parameters, we expect each one to generate a
1169 // new tab; if there are none then we get one homepage tab.
1170 int expected_tab_count = 1;
1171 if (command_line.HasSwitch(switches::kNoStartupWindow) &&
1172 !command_line.HasSwitch(switches::kAutoLaunchAtStartup)) {
1173 expected_tab_count = 0;
1174 #if defined(OS_CHROMEOS)
1175 // kLoginManager will cause Chrome to start up with the ChromeOS login
1176 // screen instead of a browser window, so it won't load any tabs.
1177 } else if (command_line.HasSwitch(switches::kLoginManager)) {
1178 expected_tab_count = 0;
1179 #endif
1180 } else if (command_line.HasSwitch(switches::kRestoreLastSession)) {
1181 std::string restore_session_value(
1182 command_line.GetSwitchValueASCII(switches::kRestoreLastSession));
1183 base::StringToInt(restore_session_value, &expected_tab_count);
1184 } else {
1185 std::vector<GURL> urls_to_open = GetURLsFromCommandLine(
1186 command_line, cur_dir, last_used_profile);
1187 expected_tab_count =
1188 std::max(1, static_cast<int>(urls_to_open.size()));
1189 }
1190 if (!CreateAutomationProvider<TestingAutomationProvider>(
1191 testing_channel_id,
1192 last_used_profile,
1193 static_cast<size_t>(expected_tab_count)))
1194 return false;
1195 }
1196
1197 if (command_line.HasSwitch(switches::kAutomationClientChannelID)) {
1198 std::string automation_channel_id = command_line.GetSwitchValueASCII(
1199 switches::kAutomationClientChannelID);
1200 // If there are any extra parameters, we expect each one to generate a
1201 // new tab; if there are none then we have no tabs
1202 std::vector<GURL> urls_to_open = GetURLsFromCommandLine(
1203 command_line, cur_dir, last_used_profile);
1204 size_t expected_tabs =
1205 std::max(static_cast<int>(urls_to_open.size()), 0);
1206 if (expected_tabs == 0)
1207 silent_launch = true;
1208
1209 if (command_line.HasSwitch(switches::kChromeFrame)) {
1210 #if !defined(USE_AURA)
1211 if (!CreateAutomationProvider<ChromeFrameAutomationProvider>(
1212 automation_channel_id, last_used_profile, expected_tabs))
1213 return false;
1214 #endif
1215 } else {
1216 if (!CreateAutomationProvider<AutomationProvider>(
1217 automation_channel_id, last_used_profile, expected_tabs))
1218 return false;
1219 }
1220 }
1221 #endif // defined(ENABLE_AUTOMATION)
1222
1223 // If we have been invoked to display a desktop notification on behalf of
1224 // the service process, we do not want to open any browser windows.
1225 if (command_line.HasSwitch(switches::kNotifyCloudPrintTokenExpired)) {
1226 silent_launch = true;
1227 CloudPrintProxyServiceFactory::GetForProfile(last_used_profile)->
1228 ShowTokenExpiredNotification();
1229 }
1230
1231 // If we are just displaying a print dialog we shouldn't open browser
1232 // windows.
1233 if (command_line.HasSwitch(switches::kCloudPrintFile) &&
1234 print_dialog_cloud::CreatePrintDialogFromCommandLine(command_line)) {
1235 silent_launch = true;
1236 }
1237
1238 // If we are checking the proxy enabled policy, don't open any windows.
1239 if (command_line.HasSwitch(switches::kCheckCloudPrintConnectorPolicy)) {
1240 silent_launch = true;
1241 if (CloudPrintProxyServiceFactory::GetForProfile(last_used_profile)->
1242 EnforceCloudPrintConnectorPolicyAndQuit())
1243 // Success, nothing more needs to be done, so return false to stop
1244 // launching and quit.
1245 return false;
1246 }
1247
1248 if (command_line.HasSwitch(switches::kExplicitlyAllowedPorts)) {
1249 std::string allowed_ports =
1250 command_line.GetSwitchValueASCII(switches::kExplicitlyAllowedPorts);
1251 net::SetExplicitlyAllowedPorts(allowed_ports);
1252 }
1253
1254 #if defined(OS_CHROMEOS)
1255 // The browser will be launched after the user logs in.
1256 if (command_line.HasSwitch(switches::kLoginManager) ||
1257 command_line.HasSwitch(switches::kLoginPassword)) {
1258 silent_launch = true;
1259 }
1260 #endif
1261
1262 #if defined(TOOLKIT_VIEWS) && defined(OS_LINUX)
1263 // Get a list of pointer-devices that should be treated as touch-devices.
1264 // This is primarily used for testing/debugging touch-event processing when a
1265 // touch-device isn't available.
1266 std::string touch_devices =
1267 command_line.GetSwitchValueASCII(switches::kTouchDevices);
1268
1269 if (!touch_devices.empty()) {
1270 std::vector<std::string> devs;
1271 std::vector<unsigned int> device_ids;
1272 unsigned int devid;
1273 base::SplitString(touch_devices, ',', &devs);
1274 for (std::vector<std::string>::iterator iter = devs.begin();
1275 iter != devs.end(); ++iter) {
1276 if (base::StringToInt(*iter, reinterpret_cast<int*>(&devid)))
1277 device_ids.push_back(devid);
1278 else
1279 DLOG(WARNING) << "Invalid touch-device id: " << *iter;
1280 }
1281 ui::TouchFactory::GetInstance()->SetTouchDeviceList(device_ids);
1282 }
1283 #endif
1284
1285 // If we don't want to launch a new browser window or tab (in the case
1286 // of an automation request), we are done here.
1287 if (!silent_launch) {
1288 IsProcessStartup is_process_startup = process_startup ?
1289 IS_PROCESS_STARTUP : IS_NOT_PROCESS_STARTUP;
1290 IsFirstRun is_first_run = first_run::IsChromeFirstRun() ?
1291 IS_FIRST_RUN : IS_NOT_FIRST_RUN;
1292 // |last_opened_profiles| will be empty in the following circumstances:
1293 // - This is the first launch. |last_used_profile| is the initial profile.
1294 // - The user exited the browser by closing all windows for all
1295 // profiles. |last_used_profile| is the profile which owned the last open
1296 // window.
1297 // - Only incognito windows were open when the browser exited.
1298 // |last_used_profile| is the last used incognito profile. Restoring it will
1299 // create a browser window for the corresponding original profile.
1300 if (last_opened_profiles.empty()) {
1301 if (!browser_init->LaunchBrowser(command_line, last_used_profile, cur_dir,
1302 is_process_startup, is_first_run, return_code))
1303 return false;
1304 } else {
1305 // Launch the last used profile with the full command line, and the other
1306 // opened profiles without the URLs to launch.
1307 CommandLine command_line_without_urls(command_line.GetProgram());
1308 const CommandLine::SwitchMap& switches = command_line.GetSwitches();
1309 for (CommandLine::SwitchMap::const_iterator switch_it = switches.begin();
1310 switch_it != switches.end(); ++switch_it) {
1311 command_line_without_urls.AppendSwitchNative(switch_it->first,
1312 switch_it->second);
1313 }
1314 // Launch the profiles in the order they became active.
1315 for (Profiles::const_iterator it = last_opened_profiles.begin();
1316 it != last_opened_profiles.end(); ++it) {
1317 // Don't launch additional profiles which would only open a new tab
1318 // page. When restarting after an update, all profiles will reopen last
1319 // open pages.
1320 SessionStartupPref startup_pref =
1321 GetSessionStartupPref(command_line, *it);
1322 if (*it != last_used_profile &&
1323 startup_pref.type == SessionStartupPref::DEFAULT &&
1324 !HasPendingUncleanExit(*it))
1325 continue;
1326 if (!browser_init->LaunchBrowser((*it == last_used_profile) ?
1327 command_line : command_line_without_urls, *it, cur_dir,
1328 is_process_startup, is_first_run, return_code))
1329 return false;
1330 // We've launched at least one browser.
1331 is_process_startup = BrowserInit::IS_NOT_PROCESS_STARTUP;
1332 }
1333 }
1334 }
1335 return true;
1336 }
1337
1338 template <class AutomationProviderClass>
1339 bool BrowserInit::CreateAutomationProvider(const std::string& channel_id,
1340 Profile* profile,
1341 size_t expected_tabs) {
1342 #if defined(ENABLE_AUTOMATION)
1343 scoped_refptr<AutomationProviderClass> automation =
1344 new AutomationProviderClass(profile);
1345 if (!automation->InitializeChannel(channel_id))
1346 return false;
1347 automation->SetExpectedTabCount(expected_tabs);
1348
1349 AutomationProviderList* list = g_browser_process->GetAutomationProviderList();
1350 DCHECK(list);
1351 list->AddProvider(automation);
1352 #endif // defined(ENABLE_AUTOMATION)
1353
1354 return true;
1355 }
1356
1357 // static
1358 void BrowserInit::ProcessCommandLineOnProfileCreated(
1359 const CommandLine& cmd_line,
1360 const FilePath& cur_dir,
1361 Profile* profile,
1362 Profile::CreateStatus status) {
1363 if (status == Profile::CREATE_STATUS_INITIALIZED)
1364 ProcessCmdLineImpl(cmd_line, cur_dir, false, profile, Profiles(), NULL,
1365 NULL);
1366 }
1367
1368 // static
1369 void BrowserInit::ProcessCommandLineAlreadyRunning(const CommandLine& cmd_line,
1370 const FilePath& cur_dir) {
1371 if (cmd_line.HasSwitch(switches::kProfileDirectory)) {
1372 ProfileManager* profile_manager = g_browser_process->profile_manager();
1373 FilePath path = cmd_line.GetSwitchValuePath(switches::kProfileDirectory);
1374 path = profile_manager->user_data_dir().Append(path);
1375 profile_manager->CreateProfileAsync(path,
1376 base::Bind(&BrowserInit::ProcessCommandLineOnProfileCreated,
1377 cmd_line, cur_dir));
1378 return;
1379 }
1380
1381 Profile* profile = ProfileManager::GetLastUsedProfile();
1382 if (!profile) {
1383 // We should only be able to get here if the profile already exists and
1384 // has been created.
1385 NOTREACHED();
1386 return;
1387 }
1388 ProcessCmdLineImpl(cmd_line, cur_dir, false, profile, Profiles(), NULL, NULL);
1389 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/browser_init.h ('k') | chrome/browser/ui/browser_init_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698