#include "base/mac/mac_util.h"
#include "base/mac/sdk_forward_declarations.h"
#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/sys_string_conversions.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/first_run/first_run.h"
#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/mac/handoff_utility.h"
#include "chrome/browser/mac/mac_startup_profiler.h"
#include "chrome/browser/profiles/profile_info_cache_observer.h"
#include "chrome/browser/profiles/profile_manager.h"
- (void)updateConfirmToQuitPrefMenuItem:(NSMenuItem*)item;
- (void)updateDisplayMessageCenterPrefMenuItem:(NSMenuItem*)item;
- (void)registerServicesMenuTypesTo:(NSApplication*)app;
-- (void)openUrls:(const std::vector<GURL>&)urls;
- (void)getUrl:(NSAppleEventDescriptor*)event
withReply:(NSAppleEventDescriptor*)reply;
- (void)windowLayeringDidChange:(NSNotification*)inNotification;
- (BOOL)shouldQuitWithInProgressDownloads;
- (void)executeApplication:(id)sender;
- (void)profileWasRemoved:(const base::FilePath&)profilePath;
+
+// Opens a tab for each GURL in |urls|.
+- (void)openUrls:(const std::vector<GURL>&)urls;
+
+// This class cannot open urls until startup has finished. The urls that cannot
+// be opened are cached in |startupUrls_|. This method must be called exactly
+// once after startup has completed. It opens the urls in |startupUrls_|, and
+// clears |startupUrls_|.
+- (void)openStartupUrls;
+
+// Opens a tab for each GURL in |urls|. If there is exactly one tab open before
+// this method is called, and that tab is the NTP, then this method closes the
+// NTP after all the |urls| have been opened.
+- (void)openUrlsReplacingNTP:(const std::vector<GURL>&)urls;
@end
class AppControllerProfileObserver : public ProfileInfoCacheObserver {
profile_manager_->GetProfileInfoCache().AddObserver(this);
}
- virtual ~AppControllerProfileObserver() {
+ ~AppControllerProfileObserver() override {
DCHECK(profile_manager_);
profile_manager_->GetProfileInfoCache().RemoveObserver(this);
}
private:
// ProfileInfoCacheObserver implementation:
- virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE {
- }
+ void OnProfileAdded(const base::FilePath& profile_path) override {}
- virtual void OnProfileWasRemoved(
- const base::FilePath& profile_path,
- const base::string16& profile_name) OVERRIDE {
+ void OnProfileWasRemoved(const base::FilePath& profile_path,
+ const base::string16& profile_name) override {
// When a profile is deleted we need to notify the AppController,
// so it can correctly update its pointer to the last used profile.
[app_controller_ profileWasRemoved:profile_path];
}
- virtual void OnProfileWillBeRemoved(
- const base::FilePath& profile_path) OVERRIDE {
- }
+ void OnProfileWillBeRemoved(const base::FilePath& profile_path) override {}
- virtual void OnProfileNameChanged(
- const base::FilePath& profile_path,
- const base::string16& old_profile_name) OVERRIDE {
- }
+ void OnProfileNameChanged(const base::FilePath& profile_path,
+ const base::string16& old_profile_name) override {}
- virtual void OnProfileAvatarChanged(
- const base::FilePath& profile_path) OVERRIDE {
- }
+ void OnProfileAvatarChanged(const base::FilePath& profile_path) override {}
ProfileManager* profile_manager_;
}
- (void)openStartupUrls {
+ DCHECK(startupComplete_);
+ [self openUrlsReplacingNTP:startupUrls_];
+ startupUrls_.clear();
+}
+
+- (void)openUrlsReplacingNTP:(const std::vector<GURL>&)urls {
+ if (urls.empty())
+ return;
+
// On Mac, the URLs are passed in via Cocoa, not command line. The Chrome
// NSApplication is created in MainMessageLoop, and then the shortcut urls
// are passed in via Apple events. At this point, the first browser is
// before PreMainMessageLoop to capture shortcut URL events, it may cause
// more problems because it relies on things created in PreMainMessageLoop
// and may break existing message loop design.
- if (startupUrls_.empty())
+
+ // If the browser hasn't started yet, just queue up the URLs.
+ if (!startupComplete_) {
+ startupUrls_.insert(startupUrls_.end(), urls.begin(), urls.end());
return;
+ }
// If there's only 1 tab and the tab is NTP, close this NTP tab and open all
// startup urls in new tabs, because the omnibox will stay focused if we
startupContent = browser->tab_strip_model()->GetActiveWebContents();
}
- if (startupUrls_.size()) {
- [self openUrls:startupUrls_];
- startupUrls_.clear();
- }
+ [self openUrls:urls];
if (startupIndex != TabStripModel::kNoTab &&
startupContent->GetVisibleURL() == GURL(chrome::kChromeUINewTabURL)) {
// for a locked profile, we have to show the User Manager instead as the
// locked profile needs authentication.
if (IsProfileSignedOut(lastProfile)) {
- UserManager::Show(lastProfile->GetPath(),
+ UserManager::Show(base::FilePath(),
profiles::USER_MANAGER_NO_TUTORIAL,
profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
return;
}
break;
case IDC_TASK_MANAGER:
- content::RecordAction(UserMetricsAction("TaskManager"));
- TaskManagerMac::Show();
+ chrome::OpenTaskManager(NULL);
break;
case IDC_OPTIONS:
[self showPreferences:sender];
// so we have to show the User Manager as well.
Profile* lastProfile = [self lastProfile];
if (lastProfile->IsGuestSession() || IsProfileSignedOut(lastProfile)) {
- UserManager::Show(lastProfile->GetPath(),
+ UserManager::Show(base::FilePath(),
profiles::USER_MANAGER_NO_TUTORIAL,
profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
} else {
return profile;
}
+// Returns true if a browser window may be opened for the last active profile.
+- (bool)canOpenNewBrowser {
+ Profile* profile = [self safeLastProfileForNewWindows];
+
+ const PrefService* prefs = g_browser_process->local_state();
+ return !profile->IsGuestSession() ||
+ prefs->GetBoolean(prefs::kBrowserGuestModeEnabled);
+}
+
// Various methods to open URLs that we get in a native fashion. We use
// StartupBrowserCreator here because on the other platforms, URLs to open come
// through the ProcessSingleton, and it calls StartupBrowserCreator. It's best
// to bottleneck the openings through that for uniform handling.
-
- (void)openUrls:(const std::vector<GURL>&)urls {
- // If the browser hasn't started yet, just queue up the URLs.
if (!startupComplete_) {
startupUrls_.insert(startupUrls_.end(), urls.begin(), urls.end());
return;
std::vector<GURL> gurlVector;
gurlVector.push_back(gurl);
- [self openUrls:gurlVector];
+ [self openUrlsReplacingNTP:gurlVector];
}
- (void)application:(NSApplication*)sender
gurlVector.push_back(gurl);
}
if (!gurlVector.empty())
- [self openUrls:gurlVector];
+ [self openUrlsReplacingNTP:gurlVector];
else
NOTREACHED() << "Nothing to open!";
if (Browser* browser = ActivateBrowser([self lastProfile])) {
// Show options tab in the active browser window.
chrome::ShowSettings(browser);
- } else {
+ } else if ([self canOpenNewBrowser]) {
// No browser window, so create one for the options tab.
chrome::OpenOptionsWindow([self safeLastProfileForNewWindows]);
+ } else {
+ // No way to create a browser, default to the User Manager.
+ UserManager::Show(base::FilePath(),
+ profiles::USER_MANAGER_NO_TUTORIAL,
+ profiles::USER_MANAGER_SELECT_PROFILE_CHROME_SETTINGS);
}
}
- (IBAction)orderFrontStandardAboutPanel:(id)sender {
if (Browser* browser = ActivateBrowser([self lastProfile])) {
chrome::ShowAboutChrome(browser);
- } else {
- // No browser window, so create one for the about tab.
+ } else if ([self canOpenNewBrowser]) {
+ // No browser window, so create one for the options tab.
chrome::OpenAboutWindow([self safeLastProfileForNewWindows]);
+ } else {
+ // No way to create a browser, default to the User Manager.
+ UserManager::Show(base::FilePath(),
+ profiles::USER_MANAGER_NO_TUTORIAL,
+ profiles::USER_MANAGER_SELECT_PROFILE_ABOUT_CHROME);
}
}
return NO;
}
+ NSString* originString = base::mac::ObjCCast<NSString>(
+ [userActivity.userInfo objectForKey:handoff::kOriginKey]);
+ handoff::Origin origin = handoff::OriginFromString(originString);
+ UMA_HISTOGRAM_ENUMERATION(
+ "OSX.Handoff.Origin", origin, handoff::ORIGIN_COUNT);
+
NSURL* url = userActivity.webPageURL;
if (!url)
return NO;
std::vector<GURL> gurlVector;
gurlVector.push_back(gurl);
- [self openUrls:gurlVector];
+ [self openUrlsReplacingNTP:gurlVector];
return YES;
}