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

Side by Side Diff: chrome/browser/ui/startup/startup_browser_creator_impl.cc

Issue 10332117: Revert 136573 - Extract StartupTabs and startup types from StartupBrowserCreator. (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
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/startup/startup_browser_creator_impl.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/compiler_specific.h"
10 #include "base/environment.h"
11 #include "base/event_recorder.h"
12 #include "base/lazy_instance.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/metrics/histogram.h"
15 #include "base/path_service.h"
16 #include "base/string_number_conversions.h"
17 #include "base/string_split.h"
18 #include "base/threading/thread_restrictions.h"
19 #include "base/utf_string_conversions.h"
20 #include "chrome/browser/auto_launch_trial.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
23 #include "chrome/browser/defaults.h"
24 #include "chrome/browser/extensions/extension_creator.h"
25 #include "chrome/browser/extensions/extension_service.h"
26 #include "chrome/browser/extensions/pack_extension_job.h"
27 #include "chrome/browser/first_run/first_run.h"
28 #include "chrome/browser/net/predictor.h"
29 #include "chrome/browser/net/url_fixer_upper.h"
30 #include "chrome/browser/notifications/desktop_notification_service.h"
31 #include "chrome/browser/prefs/incognito_mode_prefs.h"
32 #include "chrome/browser/prefs/pref_service.h"
33 #include "chrome/browser/prefs/session_startup_pref.h"
34 #include "chrome/browser/profiles/profile.h"
35 #include "chrome/browser/profiles/profile_io_data.h"
36 #include "chrome/browser/protector/protected_prefs_watcher.h"
37 #include "chrome/browser/protector/protector_service.h"
38 #include "chrome/browser/protector/protector_service_factory.h"
39 #include "chrome/browser/protector/protector_utils.h"
40 #include "chrome/browser/sessions/session_restore.h"
41 #include "chrome/browser/sessions/session_service.h"
42 #include "chrome/browser/sessions/session_service_factory.h"
43 #include "chrome/browser/shell_integration.h"
44 #include "chrome/browser/tabs/pinned_tab_codec.h"
45 #include "chrome/browser/tabs/tab_strip_model.h"
46 #include "chrome/browser/ui/browser_list.h"
47 #include "chrome/browser/ui/browser_navigator.h"
48 #include "chrome/browser/ui/browser_window.h"
49 #include "chrome/browser/ui/startup/autolaunch_prompt.h"
50 #include "chrome/browser/ui/startup/bad_flags_prompt.h"
51 #include "chrome/browser/ui/startup/default_browser_prompt.h"
52 #include "chrome/browser/ui/startup/obsolete_os_prompt.h"
53 #include "chrome/browser/ui/startup/session_crashed_prompt.h"
54 #include "chrome/browser/ui/startup/startup_browser_creator.h"
55 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
56 #include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
57 #include "chrome/browser/ui/webui/sync_promo/sync_promo_trial.h"
58 #include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
59 #include "chrome/common/chrome_constants.h"
60 #include "chrome/common/chrome_notification_types.h"
61 #include "chrome/common/chrome_paths.h"
62 #include "chrome/common/chrome_result_codes.h"
63 #include "chrome/common/chrome_switches.h"
64 #include "chrome/common/chrome_version_info.h"
65 #include "chrome/common/extensions/extension_constants.h"
66 #include "chrome/common/pref_names.h"
67 #include "chrome/common/url_constants.h"
68 #include "chrome/installer/util/browser_distribution.h"
69 #include "content/public/browser/child_process_security_policy.h"
70 #include "content/public/browser/web_contents.h"
71 #include "content/public/browser/web_contents_view.h"
72 #include "grit/locale_settings.h"
73 #include "ui/base/l10n/l10n_util.h"
74 #include "ui/base/resource/resource_bundle.h"
75
76 #if defined(OS_MACOSX)
77 #include "base/mac/mac_util.h"
78 #include "chrome/browser/ui/cocoa/keystone_infobar_delegate.h"
79 #endif
80
81 #if defined(TOOLKIT_GTK)
82 #include "chrome/browser/ui/gtk/gtk_util.h"
83 #endif
84
85 #if defined(OS_WIN)
86 #include "base/win/windows_version.h"
87 #endif
88
89 using content::ChildProcessSecurityPolicy;
90 using content::WebContents;
91 using protector::ProtectedPrefsWatcher;
92 using protector::ProtectorService;
93 using protector::ProtectorServiceFactory;
94
95 extern bool in_synchronous_profile_launch;
96
97 namespace {
98
99 // Utility functions ----------------------------------------------------------
100
101 enum LaunchMode {
102 LM_TO_BE_DECIDED = 0, // Possibly direct launch or via a shortcut.
103 LM_AS_WEBAPP, // Launched as a installed web application.
104 LM_WITH_URLS, // Launched with urls in the cmd line.
105 LM_SHORTCUT_NONE, // Not launched from a shortcut.
106 LM_SHORTCUT_NONAME, // Launched from shortcut but no name available.
107 LM_SHORTCUT_UNKNOWN, // Launched from user-defined shortcut.
108 LM_SHORTCUT_QUICKLAUNCH, // Launched from the quick launch bar.
109 LM_SHORTCUT_DESKTOP, // Launched from a desktop shortcut.
110 LM_SHORTCUT_TASKBAR, // Launched from the taskbar.
111 LM_LINUX_MAC_BEOS // Other OS buckets start here.
112 };
113
114 #if defined(OS_WIN)
115 // Undocumented flag in the startup info structure tells us what shortcut was
116 // used to launch the browser. See http://www.catch22.net/tuts/undoc01 for
117 // more information. Confirmed to work on XP, Vista and Win7.
118 LaunchMode GetLaunchShortcutKind() {
119 STARTUPINFOW si = { sizeof(si) };
120 GetStartupInfoW(&si);
121 if (si.dwFlags & 0x800) {
122 if (!si.lpTitle)
123 return LM_SHORTCUT_NONAME;
124 string16 shortcut(si.lpTitle);
125 // The windows quick launch path is not localized.
126 if (shortcut.find(L"\\Quick Launch\\") != string16::npos) {
127 if (base::win::GetVersion() >= base::win::VERSION_WIN7)
128 return LM_SHORTCUT_TASKBAR;
129 else
130 return LM_SHORTCUT_QUICKLAUNCH;
131 }
132 scoped_ptr<base::Environment> env(base::Environment::Create());
133 std::string appdata_path;
134 env->GetVar("USERPROFILE", &appdata_path);
135 if (!appdata_path.empty() &&
136 shortcut.find(ASCIIToWide(appdata_path)) != std::wstring::npos)
137 return LM_SHORTCUT_DESKTOP;
138 return LM_SHORTCUT_UNKNOWN;
139 }
140 return LM_SHORTCUT_NONE;
141 }
142 #else
143 // TODO(cpu): Port to other platforms.
144 LaunchMode GetLaunchShortcutKind() {
145 return LM_LINUX_MAC_BEOS;
146 }
147 #endif
148
149 // Log in a histogram the frequency of launching by the different methods. See
150 // LaunchMode enum for the actual values of the buckets.
151 void RecordLaunchModeHistogram(LaunchMode mode) {
152 int bucket = (mode == LM_TO_BE_DECIDED) ? GetLaunchShortcutKind() : mode;
153 UMA_HISTOGRAM_COUNTS_100("Launch.Modes", bucket);
154 }
155
156 GURL GetWelcomePageURL() {
157 std::string welcome_url = l10n_util::GetStringUTF8(IDS_WELCOME_PAGE_URL);
158 return GURL(welcome_url);
159 }
160
161 void UrlsToTabs(const std::vector<GURL>& urls, StartupTabs* tabs) {
162 for (size_t i = 0; i < urls.size(); ++i) {
163 StartupTab tab;
164 tab.is_pinned = false;
165 tab.url = urls[i];
166 tabs->push_back(tab);
167 }
168 }
169
170 // Return true if the command line option --app-id is used. Set
171 // |out_extension| to the app to open, and |out_launch_container|
172 // to the type of window into which the app should be open.
173 bool GetAppLaunchContainer(
174 Profile* profile,
175 const std::string& app_id,
176 const Extension** out_extension,
177 extension_misc::LaunchContainer* out_launch_container) {
178
179 ExtensionService* extensions_service = profile->GetExtensionService();
180 const Extension* extension =
181 extensions_service->GetExtensionById(app_id, false);
182
183 // The extension with id |app_id| may have been uninstalled.
184 if (!extension)
185 return false;
186
187 // Look at preferences to find the right launch container. If no
188 // preference is set, launch as a window.
189 extension_misc::LaunchContainer launch_container =
190 extensions_service->extension_prefs()->GetLaunchContainer(
191 extension, ExtensionPrefs::LAUNCH_WINDOW);
192
193 *out_extension = extension;
194 *out_launch_container = launch_container;
195 return true;
196 }
197
198 void RecordCmdLineAppHistogram() {
199 AppLauncherHandler::RecordAppLaunchType(
200 extension_misc::APP_LAUNCH_CMD_LINE_APP);
201 }
202
203 void RecordAppLaunches(Profile* profile,
204 const std::vector<GURL>& cmd_line_urls,
205 StartupTabs& autolaunch_tabs) {
206 ExtensionService* extension_service = profile->GetExtensionService();
207 DCHECK(extension_service);
208 for (size_t i = 0; i < cmd_line_urls.size(); ++i) {
209 if (extension_service->IsInstalledApp(cmd_line_urls.at(i))) {
210 AppLauncherHandler::RecordAppLaunchType(
211 extension_misc::APP_LAUNCH_CMD_LINE_URL);
212 }
213 }
214 for (size_t i = 0; i < autolaunch_tabs.size(); ++i) {
215 if (extension_service->IsInstalledApp(autolaunch_tabs.at(i).url)) {
216 AppLauncherHandler::RecordAppLaunchType(
217 extension_misc::APP_LAUNCH_AUTOLAUNCH);
218 }
219 }
220 }
221
222 } // namespace
223
224 StartupBrowserCreatorImpl::StartupBrowserCreatorImpl(
225 const FilePath& cur_dir,
226 const CommandLine& command_line,
227 browser::startup::IsFirstRun is_first_run)
228 : cur_dir_(cur_dir),
229 command_line_(command_line),
230 profile_(NULL),
231 browser_creator_(NULL),
232 is_first_run_(is_first_run == browser::startup::IS_FIRST_RUN) {
233 }
234
235 StartupBrowserCreatorImpl::StartupBrowserCreatorImpl(
236 const FilePath& cur_dir,
237 const CommandLine& command_line,
238 StartupBrowserCreator* browser_creator,
239 browser::startup::IsFirstRun is_first_run)
240 : cur_dir_(cur_dir),
241 command_line_(command_line),
242 profile_(NULL),
243 browser_creator_(browser_creator),
244 is_first_run_(is_first_run == browser::startup::IS_FIRST_RUN) {
245 }
246
247 StartupBrowserCreatorImpl::~StartupBrowserCreatorImpl() {
248 }
249
250 bool StartupBrowserCreatorImpl::Launch(Profile* profile,
251 const std::vector<GURL>& urls_to_open,
252 bool process_startup) {
253 DCHECK(profile);
254 profile_ = profile;
255
256 if (command_line_.HasSwitch(switches::kDnsLogDetails))
257 chrome_browser_net::EnablePredictorDetailedLog(true);
258 if (command_line_.HasSwitch(switches::kDnsPrefetchDisable) &&
259 profile->GetNetworkPredictor()) {
260 profile->GetNetworkPredictor()->EnablePredictor(false);
261 }
262
263 if (command_line_.HasSwitch(switches::kDumpHistogramsOnExit))
264 base::StatisticsRecorder::set_dump_on_exit(true);
265
266 if (command_line_.HasSwitch(switches::kRemoteDebuggingPort)) {
267 std::string port_str =
268 command_line_.GetSwitchValueASCII(switches::kRemoteDebuggingPort);
269 int64 port;
270 if (base::StringToInt64(port_str, &port) && port > 0 && port < 65535) {
271 std::string frontend_str;
272 if (command_line_.HasSwitch(switches::kRemoteDebuggingFrontend)) {
273 frontend_str = command_line_.GetSwitchValueASCII(
274 switches::kRemoteDebuggingFrontend);
275 }
276 g_browser_process->InitDevToolsHttpProtocolHandler(
277 profile,
278 "127.0.0.1",
279 static_cast<int>(port),
280 frontend_str);
281 } else {
282 DLOG(WARNING) << "Invalid http debugger port number " << port;
283 }
284 }
285
286 // Open the required browser windows and tabs. First, see if
287 // we're being run as an application window. If so, the user
288 // opened an app shortcut. Don't restore tabs or open initial
289 // URLs in that case. The user should see the window as an app,
290 // not as chrome.
291 // Special case is when app switches are passed but we do want to restore
292 // session. In that case open app window + focus it after session is restored.
293 if (OpenApplicationWindow(profile) && !browser_defaults::kAppRestoreSession) {
294 RecordLaunchModeHistogram(LM_AS_WEBAPP);
295 } else {
296 Browser* browser_to_focus = NULL;
297 // In case of app mode + session restore we want to focus that app.
298 if (browser_defaults::kAppRestoreSession)
299 browser_to_focus = BrowserList::GetLastActive();
300
301 RecordLaunchModeHistogram(urls_to_open.empty()?
302 LM_TO_BE_DECIDED : LM_WITH_URLS);
303
304 // Notify user if the Preferences backup is invalid or changes to settings
305 // affecting browser startup have been detected.
306 CheckPreferencesBackup(profile);
307
308 ProcessLaunchURLs(process_startup, urls_to_open);
309
310 // If this is an app launch, but we didn't open an app window, it may
311 // be an app tab.
312 OpenApplicationTab(profile);
313
314 if (browser_to_focus)
315 browser_to_focus->GetSelectedWebContents()->GetView()->SetInitialFocus();
316
317 if (process_startup) {
318 if (browser_defaults::kOSSupportsOtherBrowsers &&
319 !command_line_.HasSwitch(switches::kNoDefaultBrowserCheck)) {
320 if (!browser::ShowAutolaunchPrompt(profile))
321 browser::ShowDefaultBrowserPrompt(profile);
322 }
323 #if defined(OS_MACOSX)
324 // Check whether the auto-update system needs to be promoted from user
325 // to system.
326 KeystoneInfoBar::PromotionInfoBar(profile);
327 #endif
328 }
329 }
330
331 #if defined(OS_WIN)
332 // Print the selected page if the command line switch exists. Note that the
333 // current selected tab would be the page which will be printed.
334 if (command_line_.HasSwitch(switches::kPrint)) {
335 Browser* browser = BrowserList::GetLastActive();
336 browser->Print();
337 }
338 #endif
339
340 // If we're recording or playing back, startup the EventRecorder now
341 // unless otherwise specified.
342 if (!command_line_.HasSwitch(switches::kNoEvents)) {
343 FilePath script_path;
344 PathService::Get(chrome::FILE_RECORDED_SCRIPT, &script_path);
345
346 bool record_mode = command_line_.HasSwitch(switches::kRecordMode);
347 bool playback_mode = command_line_.HasSwitch(switches::kPlaybackMode);
348
349 if (record_mode && chrome::kRecordModeEnabled)
350 base::EventRecorder::current()->StartRecording(script_path);
351 if (playback_mode)
352 base::EventRecorder::current()->StartPlayback(script_path);
353 }
354
355 #if defined(OS_WIN)
356 if (process_startup)
357 ShellIntegration::MigrateChromiumShortcuts();
358 #endif // defined(OS_WIN)
359
360 return true;
361 }
362
363 bool StartupBrowserCreatorImpl::IsAppLaunch(std::string* app_url,
364 std::string* app_id) {
365 if (command_line_.HasSwitch(switches::kApp)) {
366 if (app_url)
367 *app_url = command_line_.GetSwitchValueASCII(switches::kApp);
368 return true;
369 }
370 if (command_line_.HasSwitch(switches::kAppId)) {
371 if (app_id)
372 *app_id = command_line_.GetSwitchValueASCII(switches::kAppId);
373 return true;
374 }
375 return false;
376 }
377
378 bool StartupBrowserCreatorImpl::OpenApplicationTab(Profile* profile) {
379 std::string app_id;
380 // App shortcuts to URLs always open in an app window. Because this
381 // function will open an app that should be in a tab, there is no need
382 // to look at the app URL. OpenApplicationWindow() will open app url
383 // shortcuts.
384 if (!IsAppLaunch(NULL, &app_id) || app_id.empty())
385 return false;
386
387 extension_misc::LaunchContainer launch_container;
388 const Extension* extension;
389 if (!GetAppLaunchContainer(profile, app_id, &extension, &launch_container))
390 return false;
391
392 // If the user doesn't want to open a tab, fail.
393 if (launch_container != extension_misc::LAUNCH_TAB)
394 return false;
395
396 RecordCmdLineAppHistogram();
397
398 WebContents* app_tab = Browser::OpenApplicationTab(profile, extension, GURL(),
399 NEW_FOREGROUND_TAB);
400 return (app_tab != NULL);
401 }
402
403 bool StartupBrowserCreatorImpl::OpenApplicationWindow(Profile* profile) {
404 std::string url_string, app_id;
405 if (!IsAppLaunch(&url_string, &app_id))
406 return false;
407
408 // This can fail if the app_id is invalid. It can also fail if the
409 // extension is external, and has not yet been installed.
410 // TODO(skerner): Do something reasonable here. Pop up a warning panel?
411 // Open an URL to the gallery page of the extension id?
412 if (!app_id.empty()) {
413 extension_misc::LaunchContainer launch_container;
414 const Extension* extension;
415 if (!GetAppLaunchContainer(profile, app_id, &extension, &launch_container))
416 return false;
417
418 // TODO(skerner): Could pass in |extension| and |launch_container|,
419 // and avoid calling GetAppLaunchContainer() both here and in
420 // OpenApplicationTab().
421
422 if (launch_container == extension_misc::LAUNCH_TAB)
423 return false;
424
425 RecordCmdLineAppHistogram();
426 WebContents* tab_in_app_window = Browser::OpenApplication(
427 profile, extension, launch_container, GURL(), NEW_WINDOW);
428 // Platform apps fire off a launch event which may or may not open a window.
429 return (tab_in_app_window != NULL || extension->is_platform_app());
430 }
431
432 if (url_string.empty())
433 return false;
434
435 #if defined(OS_WIN) // Fix up Windows shortcuts.
436 ReplaceSubstringsAfterOffset(&url_string, 0, "\\x", "%");
437 #endif
438 GURL url(url_string);
439
440 // Restrict allowed URLs for --app switch.
441 if (!url.is_empty() && url.is_valid()) {
442 ChildProcessSecurityPolicy *policy =
443 ChildProcessSecurityPolicy::GetInstance();
444 if (policy->IsWebSafeScheme(url.scheme()) ||
445 url.SchemeIs(chrome::kFileScheme)) {
446
447 if (profile->GetExtensionService()->IsInstalledApp(url)) {
448 RecordCmdLineAppHistogram();
449 } else {
450 AppLauncherHandler::RecordAppLaunchType(
451 extension_misc::APP_LAUNCH_CMD_LINE_APP_LEGACY);
452 }
453 WebContents* app_tab = Browser::OpenAppShortcutWindow(
454 profile,
455 url,
456 true); // Update app info.
457 return (app_tab != NULL);
458 }
459 }
460 return false;
461 }
462
463 void StartupBrowserCreatorImpl::ProcessLaunchURLs(
464 bool process_startup,
465 const std::vector<GURL>& urls_to_open) {
466 // If we're starting up in "background mode" (no open browser window) then
467 // don't open any browser windows, unless kAutoLaunchAtStartup is also
468 // specified.
469 if (process_startup &&
470 command_line_.HasSwitch(switches::kNoStartupWindow) &&
471 !command_line_.HasSwitch(switches::kAutoLaunchAtStartup)) {
472 return;
473 }
474
475 if (process_startup && ProcessStartupURLs(urls_to_open)) {
476 // ProcessStartupURLs processed the urls, nothing else to do.
477 return;
478 }
479
480 browser::startup::IsProcessStartup is_process_startup = process_startup ?
481 browser::startup::IS_PROCESS_STARTUP :
482 browser::startup::IS_NOT_PROCESS_STARTUP;
483 if (!process_startup) {
484 // Even if we're not starting a new process, this may conceptually be
485 // "startup" for the user and so should be handled in a similar way. Eg.,
486 // Chrome may have been running in the background due to an app with a
487 // background page being installed, or running with only an app window
488 // displayed.
489 SessionService* service = SessionServiceFactory::GetForProfile(profile_);
490 if (service && service->ShouldNewWindowStartSession()) {
491 // Restore the last session if any.
492 if (!HasPendingUncleanExit(profile_) &&
493 service->RestoreIfNecessary(urls_to_open)) {
494 return;
495 }
496 // Open user-specified URLs like pinned tabs and startup tabs.
497 Browser* browser = ProcessSpecifiedURLs(urls_to_open);
498 if (browser) {
499 AddInfoBarsIfNecessary(browser, is_process_startup);
500 return;
501 }
502 }
503 }
504
505 // Session startup didn't occur, open the urls.
506
507 Browser* browser = NULL;
508 std::vector<GURL> adjust_urls = urls_to_open;
509 if (adjust_urls.empty())
510 AddStartupURLs(&adjust_urls);
511 else if (!command_line_.HasSwitch(switches::kOpenInNewWindow))
512 browser = BrowserList::GetLastActiveWithProfile(profile_);
513
514 // This will launch a browser; prevent session restore.
515 in_synchronous_profile_launch = true;
516 browser = OpenURLsInBrowser(browser, process_startup, adjust_urls);
517 in_synchronous_profile_launch = false;
518 AddInfoBarsIfNecessary(browser, is_process_startup);
519 }
520
521 bool StartupBrowserCreatorImpl::ProcessStartupURLs(
522 const std::vector<GURL>& urls_to_open) {
523 SessionStartupPref pref =
524 StartupBrowserCreator::GetSessionStartupPref(command_line_, profile_);
525
526 if (pref.type == SessionStartupPref::LAST) {
527 if (!profile_->DidLastSessionExitCleanly() &&
528 !command_line_.HasSwitch(switches::kRestoreLastSession)) {
529 // The last session crashed. It's possible automatically loading the
530 // page will trigger another crash, locking the user out of chrome.
531 // To avoid this, don't restore on startup but instead show the crashed
532 // infobar.
533 return false;
534 }
535
536 uint32 restore_behavior = SessionRestore::SYNCHRONOUS |
537 SessionRestore::ALWAYS_CREATE_TABBED_BROWSER;
538 #if defined(OS_MACOSX)
539 // On Mac, when restoring a session with no windows, suppress the creation
540 // of a new window in the case where the system is launching Chrome via a
541 // login item or Lion's resume feature.
542 if (base::mac::WasLaunchedAsLoginOrResumeItem()) {
543 restore_behavior = restore_behavior &
544 ~SessionRestore::ALWAYS_CREATE_TABBED_BROWSER;
545 }
546 #endif
547
548 Browser* browser = SessionRestore::RestoreSession(profile_,
549 NULL,
550 restore_behavior,
551 urls_to_open);
552 AddInfoBarsIfNecessary(browser, browser::startup::IS_PROCESS_STARTUP);
553 return true;
554 }
555
556 Browser* browser = ProcessSpecifiedURLs(urls_to_open);
557 if (!browser)
558 return false;
559
560 AddInfoBarsIfNecessary(browser, browser::startup::IS_PROCESS_STARTUP);
561 return true;
562 }
563
564 Browser* StartupBrowserCreatorImpl::ProcessSpecifiedURLs(
565 const std::vector<GURL>& urls_to_open) {
566 SessionStartupPref pref =
567 StartupBrowserCreator::GetSessionStartupPref(command_line_, profile_);
568 StartupTabs tabs;
569 // Pinned tabs should not be displayed when chrome is launched in incognito
570 // mode. Also, no pages should be opened automatically if the session
571 // crashed. Otherwise it might trigger another crash, locking the user out of
572 // chrome. The crash infobar is shown in this case.
573 if (!IncognitoModePrefs::ShouldLaunchIncognito(command_line_,
574 profile_->GetPrefs()) &&
575 !HasPendingUncleanExit(profile_)) {
576 tabs = PinnedTabCodec::ReadPinnedTabs(profile_);
577 }
578
579 RecordAppLaunches(profile_, urls_to_open, tabs);
580
581 if (!urls_to_open.empty()) {
582 // If urls were specified on the command line, use them.
583 UrlsToTabs(urls_to_open, &tabs);
584 } else if (pref.type == SessionStartupPref::URLS && !pref.urls.empty() &&
585 !HasPendingUncleanExit(profile_)) {
586 // Only use the set of urls specified in preferences if nothing was
587 // specified on the command line. Filter out any urls that are to be
588 // restored by virtue of having been previously pinned.
589 AddUniqueURLs(pref.urls, &tabs);
590 } else if (pref.type == SessionStartupPref::DEFAULT) {
591 std::vector<GURL> urls;
592 AddStartupURLs(&urls);
593 UrlsToTabs(urls, &tabs);
594
595 } else if (pref.type == SessionStartupPref::HOMEPAGE) {
596 // If 'homepage' selected, either by the user or by a policy, we should
597 // have migrated them to another value.
598 NOTREACHED() << "SessionStartupPref has deprecated type HOMEPAGE";
599 }
600
601 if (tabs.empty())
602 return NULL;
603
604 Browser* browser = OpenTabsInBrowser(NULL, true, tabs);
605 return browser;
606 }
607
608 void StartupBrowserCreatorImpl::AddUniqueURLs(const std::vector<GURL>& urls,
609 StartupTabs* tabs) {
610 size_t num_existing_tabs = tabs->size();
611 for (size_t i = 0; i < urls.size(); ++i) {
612 bool in_tabs = false;
613 for (size_t j = 0; j < num_existing_tabs; ++j) {
614 if (urls[i] == (*tabs)[j].url) {
615 in_tabs = true;
616 break;
617 }
618 }
619 if (!in_tabs) {
620 StartupTab tab;
621 tab.is_pinned = false;
622 tab.url = urls[i];
623 tabs->push_back(tab);
624 }
625 }
626 }
627
628 Browser* StartupBrowserCreatorImpl::OpenURLsInBrowser(
629 Browser* browser,
630 bool process_startup,
631 const std::vector<GURL>& urls) {
632 StartupTabs tabs;
633 UrlsToTabs(urls, &tabs);
634 return OpenTabsInBrowser(browser, process_startup, tabs);
635 }
636
637 Browser* StartupBrowserCreatorImpl::OpenTabsInBrowser(Browser* browser,
638 bool process_startup,
639 const StartupTabs& tabs) {
640 DCHECK(!tabs.empty());
641
642 // If we don't yet have a profile, try to use the one we're given from
643 // |browser|. While we may not end up actually using |browser| (since it
644 // could be a popup window), we can at least use the profile.
645 if (!profile_ && browser)
646 profile_ = browser->profile();
647
648 if (!browser || !browser->is_type_tabbed()) {
649 browser = Browser::Create(profile_);
650 } else {
651 #if defined(TOOLKIT_GTK)
652 // Setting the time of the last action on the window here allows us to steal
653 // focus, which is what the user wants when opening a new tab in an existing
654 // browser window.
655 gtk_util::SetWMLastUserActionTime(browser->window()->GetNativeHandle());
656 #endif
657 }
658
659 #if !defined(OS_MACOSX)
660 // In kiosk mode, we want to always be fullscreen, so switch to that now.
661 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
662 browser->ToggleFullscreenMode();
663 #endif
664
665 bool first_tab = true;
666 for (size_t i = 0; i < tabs.size(); ++i) {
667 // We skip URLs that we'd have to launch an external protocol handler for.
668 // This avoids us getting into an infinite loop asking ourselves to open
669 // a URL, should the handler be (incorrectly) configured to be us. Anyone
670 // asking us to open such a URL should really ask the handler directly.
671 bool handled_by_chrome = ProfileIOData::IsHandledURL(tabs[i].url) ||
672 (profile_ && profile_->GetProtocolHandlerRegistry()->IsHandledProtocol(
673 tabs[i].url.scheme()));
674 if (!process_startup && !handled_by_chrome)
675 continue;
676
677 int add_types = first_tab ? TabStripModel::ADD_ACTIVE :
678 TabStripModel::ADD_NONE;
679 add_types |= TabStripModel::ADD_FORCE_INDEX;
680 if (tabs[i].is_pinned)
681 add_types |= TabStripModel::ADD_PINNED;
682 int index = browser->GetIndexForInsertionDuringRestore(i);
683
684 browser::NavigateParams params(browser, tabs[i].url,
685 content::PAGE_TRANSITION_START_PAGE);
686 params.disposition = first_tab ? NEW_FOREGROUND_TAB :
687 NEW_BACKGROUND_TAB;
688 params.tabstrip_index = index;
689 params.tabstrip_add_types = add_types;
690 params.extension_app_id = tabs[i].app_id;
691 browser::Navigate(&params);
692
693 first_tab = false;
694 }
695 if (!browser->GetSelectedWebContents()) {
696 // TODO: this is a work around for 110909. Figure out why it's needed.
697 if (!browser->tab_count())
698 browser->AddBlankTab(true);
699 else
700 browser->ActivateTabAt(0, false);
701 }
702
703 browser->window()->Show();
704 // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
705 // focus explicitly.
706 browser->GetSelectedWebContents()->GetView()->SetInitialFocus();
707
708 return browser;
709 }
710
711 void StartupBrowserCreatorImpl::AddInfoBarsIfNecessary(
712 Browser* browser,
713 browser::startup::IsProcessStartup is_process_startup) {
714 if (!browser || !profile_ || browser->tab_count() == 0)
715 return;
716
717 if (HasPendingUncleanExit(browser->profile()))
718 browser::ShowSessionCrashedPrompt(browser);
719
720 // The bad flags info bar and the obsolete system info bar are only added to
721 // the first profile which is launched. Other profiles might be restoring the
722 // browsing sessions asynchronously, so we cannot add the info bars to the
723 // focused tabs here.
724 if (is_process_startup == browser::startup::IS_PROCESS_STARTUP) {
725 browser::ShowBadFlagsPrompt(browser);
726 browser::ShowObsoleteOSPrompt(browser);
727 }
728 }
729
730
731 void StartupBrowserCreatorImpl::AddStartupURLs(
732 std::vector<GURL>* startup_urls) const {
733 // If we have urls specified beforehand (i.e. from command line) use them
734 // and nothing else.
735 if (!startup_urls->empty())
736 return;
737
738 // If we have urls specified by the first run master preferences use them
739 // and nothing else.
740 if (browser_creator_) {
741 if (!browser_creator_->first_run_tabs_.empty()) {
742 std::vector<GURL>::iterator it =
743 browser_creator_->first_run_tabs_.begin();
744 while (it != browser_creator_->first_run_tabs_.end()) {
745 // Replace magic names for the actual urls.
746 if (it->host() == "new_tab_page") {
747 startup_urls->push_back(GURL(chrome::kChromeUINewTabURL));
748 } else if (it->host() == "welcome_page") {
749 startup_urls->push_back(GetWelcomePageURL());
750 } else {
751 startup_urls->push_back(*it);
752 }
753 ++it;
754 }
755 browser_creator_->first_run_tabs_.clear();
756 }
757 }
758
759 // Otherwise open at least the new tab page (and the welcome page, if this
760 // is the first time the browser is being started), or the set of URLs
761 // specified on the command line.
762 if (startup_urls->empty()) {
763 startup_urls->push_back(GURL(chrome::kChromeUINewTabURL));
764 PrefService* prefs = g_browser_process->local_state();
765 if (prefs->FindPreference(prefs::kShouldShowWelcomePage) &&
766 prefs->GetBoolean(prefs::kShouldShowWelcomePage)) {
767 // Reset the preference so we don't show the welcome page next time.
768 prefs->ClearPref(prefs::kShouldShowWelcomePage);
769 startup_urls->push_back(GetWelcomePageURL());
770 }
771 }
772
773 // If the sync promo page is going to be displayed then insert it at the front
774 // of the list.
775 if (SyncPromoUI::ShouldShowSyncPromoAtStartup(profile_, is_first_run_)) {
776 SyncPromoUI::DidShowSyncPromoAtStartup(profile_);
777 GURL old_url = (*startup_urls)[0];
778 (*startup_urls)[0] =
779 SyncPromoUI::GetSyncPromoURL(GURL(chrome::kChromeUINewTabURL),
780 SyncPromoUI::SOURCE_START_PAGE);
781
782 // An empty URL means to go to the home page.
783 if (old_url.is_empty() &&
784 profile_->GetHomePage() == GURL(chrome::kChromeUINewTabURL)) {
785 old_url = GURL(chrome::kChromeUINewTabURL);
786 }
787
788 // If the old URL is not the NTP then insert it right after the sync promo.
789 if (old_url != GURL(chrome::kChromeUINewTabURL))
790 startup_urls->insert(startup_urls->begin() + 1, old_url);
791
792 // If we have more than two startup tabs then skip the welcome page.
793 if (startup_urls->size() > 2) {
794 std::vector<GURL>::iterator it = std::find(
795 startup_urls->begin(), startup_urls->end(), GetWelcomePageURL());
796 if (it != startup_urls->end())
797 startup_urls->erase(it);
798 }
799 }
800 }
801
802 void StartupBrowserCreatorImpl::CheckPreferencesBackup(Profile* profile) {
803 ProtectorService* protector_service =
804 ProtectorServiceFactory::GetForProfile(profile);
805 ProtectedPrefsWatcher* prefs_watcher = protector_service->GetPrefsWatcher();
806
807 // Check if backup is valid.
808 if (!prefs_watcher->is_backup_valid()) {
809 protector_service->ShowChange(protector::CreatePrefsBackupInvalidChange());
810 // Further checks make no sense.
811 return;
812 }
813
814 // Check for session startup (including pinned tabs) changes.
815 if (SessionStartupPref::DidStartupPrefChange(profile) ||
816 prefs_watcher->DidPrefChange(prefs::kPinnedTabs)) {
817 LOG(WARNING) << "Session startup settings have changed";
818 SessionStartupPref new_pref = SessionStartupPref::GetStartupPref(profile);
819 StartupTabs new_tabs = PinnedTabCodec::ReadPinnedTabs(profile);
820 const base::Value* tabs_backup =
821 prefs_watcher->GetBackupForPref(prefs::kPinnedTabs);
822 protector_service->ShowChange(protector::CreateSessionStartupChange(
823 new_pref,
824 new_tabs,
825 SessionStartupPref::GetStartupPrefBackup(profile),
826 PinnedTabCodec::ReadPinnedTabs(tabs_backup)));
827 }
828
829 // Check for homepage changes.
830 if (prefs_watcher->DidPrefChange(prefs::kHomePage) ||
831 prefs_watcher->DidPrefChange(prefs::kHomePageIsNewTabPage) ||
832 prefs_watcher->DidPrefChange(prefs::kShowHomeButton)) {
833 LOG(WARNING) << "Homepage has changed";
834 PrefService* prefs = profile->GetPrefs();
835 std::string backup_homepage;
836 bool backup_homepage_is_ntp;
837 bool backup_show_home_button;
838 if (!prefs_watcher->GetBackupForPref(prefs::kHomePage)->
839 GetAsString(&backup_homepage) ||
840 !prefs_watcher->GetBackupForPref(prefs::kHomePageIsNewTabPage)->
841 GetAsBoolean(&backup_homepage_is_ntp) ||
842 !prefs_watcher->GetBackupForPref(prefs::kShowHomeButton)->
843 GetAsBoolean(&backup_show_home_button)) {
844 NOTREACHED();
845 }
846 protector_service->ShowChange(protector::CreateHomepageChange(
847 // New:
848 prefs->GetString(prefs::kHomePage),
849 prefs->GetBoolean(prefs::kHomePageIsNewTabPage),
850 prefs->GetBoolean(prefs::kShowHomeButton),
851 // Backup:
852 backup_homepage,
853 backup_homepage_is_ntp,
854 backup_show_home_button));
855 }
856 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/startup/startup_browser_creator_impl.h ('k') | chrome/browser/ui/startup/startup_tab.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698