diff options
author | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 04:52:56 +0000 |
---|---|---|
committer | viettrungluu@chromium.org <viettrungluu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-22 04:52:56 +0000 |
commit | ddf124cb8f239ecfbe2339d16f4e3dc849798d20 (patch) | |
tree | efd60310a937d87d9dfd48816779dad690111d83 /chrome/browser | |
parent | 0f7a0191f603800bbf7e387277ed29a6209063bc (diff) | |
download | chromium_src-ddf124cb8f239ecfbe2339d16f4e3dc849798d20.zip chromium_src-ddf124cb8f239ecfbe2339d16f4e3dc849798d20.tar.gz chromium_src-ddf124cb8f239ecfbe2339d16f4e3dc849798d20.tar.bz2 |
Getting perf numbers. Will revert.
BUG=none
TEST=none
TBR=viettrungluu@chromium.org
Review URL: http://codereview.chromium.org/502099
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35137 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/app_controller_mac.h | 18 | ||||
-rw-r--r-- | chrome/browser/app_controller_mac.mm | 76 | ||||
-rw-r--r-- | chrome/browser/browser_init.cc | 10 | ||||
-rw-r--r-- | chrome/browser/browser_main.cc | 17 | ||||
-rw-r--r-- | chrome/browser/browser_main.h | 22 | ||||
-rw-r--r-- | chrome/browser/browser_main_mac.mm | 18 |
6 files changed, 103 insertions, 58 deletions
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h index ba04a49..4ff1eb0 100644 --- a/chrome/browser/app_controller_mac.h +++ b/chrome/browser/app_controller_mac.h @@ -33,10 +33,12 @@ class Profile; PreferencesWindowController* prefsController_; // Weak. AboutWindowController* aboutController_; // Weak. - // URLs that need to be opened when the app is fully initialized. Because it's - // only needed during early startup, it points to a valid vector during early - // startup and is NULL during the rest of app execution. - scoped_ptr<std::vector<GURL> > pendingURLs_; + // If we're told to open URLs (in particular, via |-application:openFiles:| by + // Launch Services) before we've launched the browser, we queue them up in + // |startupURLs_| so that they can go in the first browser window/tab. + // |startupComplete_| is automatically initialized to |NO|. + std::vector<GURL> startupURLs_; + BOOL startupComplete_; // Outlets for the close tab/window menu items so that we can adjust the // commmand-key equivalent depending on the kind of window and how many @@ -50,6 +52,8 @@ class Profile; IBOutlet NSMenu* helpMenu_; } +@property(readonly, nonatomic) BOOL startupComplete; + - (void)didEndMainMessageLoop; - (Profile*)defaultProfile; @@ -64,6 +68,12 @@ class Profile; // Delegate method to return the dock menu. - (NSMenu*)applicationDockMenu:(NSApplication*)sender; +// Get the URLs that Launch Services expects the browser to open at startup. +- (const std::vector<GURL>&)startupURLs; + +// Clear the list of startup URLs. +- (void)clearStartupURLs; + @end #endif diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 08d61b8..f465b17 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm @@ -45,6 +45,7 @@ #include "chrome/common/temp_scaffolding_stubs.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" +#include "net/base/net_util.h" // 10.6 adds a public API for the Spotlight-backed search menu item in the Help // menu. Provide the declaration so it can be called below when building with @@ -80,12 +81,12 @@ static bool g_is_opening_new_window = false; @implementation AppController +@synthesize startupComplete = startupComplete_; + // This method is called very early in application startup (ie, before // the profile is loaded or any preferences have been registered). Defer any // user-data initialization until -applicationDidFinishLaunching:. - (void)awakeFromNib { - pendingURLs_.reset(new std::vector<GURL>()); - // We need to register the handlers early to catch events fired on launch. NSAppleEventManager* em = [NSAppleEventManager sharedAppleEventManager]; [em setEventHandler:self @@ -96,10 +97,6 @@ static bool g_is_opening_new_window = false; andSelector:@selector(getUrl:withReply:) forEventClass:'WWW!' // A particularly ancient AppleEvent that dates andEventID:'OURL']; // back to the Spyglass days. - [em setEventHandler:self - andSelector:@selector(openFiles:withReply:) - forEventClass:kCoreEventClass - andEventID:kAEOpenDocuments]; // Register for various window layering changes. We use these to update // various UI elements (command-key equivalents, etc) when the frontmost @@ -353,12 +350,10 @@ static bool g_is_opening_new_window = false; // Since Chrome is localized to more languages than the OS, tell Cocoa which // menu is the Help so it can add the search item to it. - if (helpMenu_ && [NSApp respondsToSelector:@selector(setHelpMenu:)]) { + if (helpMenu_ && [NSApp respondsToSelector:@selector(setHelpMenu:)]) [NSApp setHelpMenu:helpMenu_]; - } - // Now that we're initialized we can open any URLs we've been holding onto. - [self openPendingURLs]; + startupComplete_ = YES; } // This is called after profiles have been loaded and preferences registered. @@ -659,9 +654,9 @@ static bool g_is_opening_new_window = false; // openings through that for uniform handling. - (void)openURLs:(const std::vector<GURL>&)urls { - if (pendingURLs_.get()) { - // too early to open; save for later - pendingURLs_->insert(pendingURLs_->end(), urls.begin(), urls.end()); + // If the browser hasn't started yet, just queue up the URLs. + if (!startupComplete_) { + startupURLs_.insert(startupURLs_.end(), urls.begin(), urls.end()); return; } @@ -677,17 +672,6 @@ static bool g_is_opening_new_window = false; launch.OpenURLsInBrowser(browser, false, urls); } -- (void)openPendingURLs { - // Since the existence of pendingURLs_ is a flag that it's too early to - // open URLs, we need to reset pendingURLs_. - std::vector<GURL> urls; - swap(urls, *pendingURLs_); - pendingURLs_.reset(); - - if (urls.size()) - [self openURLs:urls]; -} - - (void)getUrl:(NSAppleEventDescriptor*)event withReply:(NSAppleEventDescriptor*)reply { NSString* urlStr = [[event paramDescriptorForKeyword:keyDirectObject] @@ -700,37 +684,19 @@ static bool g_is_opening_new_window = false; [self openURLs:gurlVector]; } -- (void)openFiles:(NSAppleEventDescriptor*)event - withReply:(NSAppleEventDescriptor*)reply { - // Ordinarily we'd use the NSApplication delegate method - // -application:openFiles:, but Cocoa tries to be smart and it sends files - // specified on the command line into that delegate method. That's too smart - // for us (our setup isn't done by the time Cocoa triggers the delegate method - // and we crash). Since all we want are files dropped on the app icon, and we - // have cross-platform code to handle the command-line files anyway, an Apple - // Event handler fits the bill just right. - NSAppleEventDescriptor* fileList = - [event paramDescriptorForKeyword:keyDirectObject]; - if (!fileList) - return; +- (void)application:(NSApplication*)sender + openFiles:(NSArray*)filenames { std::vector<GURL> gurlVector; - - for (NSInteger i = 1; i <= [fileList numberOfItems]; ++i) { - NSAppleEventDescriptor* fileAliasDesc = [fileList descriptorAtIndex:i]; - if (!fileAliasDesc) - continue; - NSAppleEventDescriptor* fileURLDesc = - [fileAliasDesc coerceToDescriptorType:typeFileURL]; - if (!fileURLDesc) - continue; - NSData* fileURLData = [fileURLDesc data]; - if (!fileURLData) - continue; - GURL gurl(std::string((char*)[fileURLData bytes], [fileURLData length])); + for (NSString* file in filenames) { + GURL gurl = net::FilePathToFileURL(FilePath(base::SysNSStringToUTF8(file))); gurlVector.push_back(gurl); } + if (!gurlVector.empty()) + [self openURLs:gurlVector]; + else + NOTREACHED() << "Nothing to open!"; - [self openURLs:gurlVector]; + [sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; } // Called when the preferences window is closed. We use this to release the @@ -834,6 +800,14 @@ static bool g_is_opening_new_window = false; return dockMenu; } +- (const std::vector<GURL>&)startupURLs { + return startupURLs_; +} + +- (void)clearStartupURLs { + startupURLs_.clear(); +} + @end //--------------------------------------------------------------------------- diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index 3ccb82f..aa8f451 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -47,6 +47,7 @@ #include "webkit/glue/webkit_glue.h" #if defined(OS_MACOSX) +#include "chrome/browser/browser_main.h" #include "chrome/browser/cocoa/keystone_infobar.h" #endif @@ -647,6 +648,15 @@ std::vector<GURL> BrowserInit::LaunchWithProfile::GetURLsFromCommandLine( void BrowserInit::LaunchWithProfile::AddStartupURLs( std::vector<GURL>* startup_urls) const { +#if defined(OS_MACOSX) + // On Mac, startup URLs are usually delivered by Launch Services, not on the + // command line. Get them. + DCHECK(Platform::IsStartupComplete()); + startup_urls->insert(startup_urls->end(), Platform::GetStartupURLs().begin(), + Platform::GetStartupURLs().end()); + Platform::ClearStartupURLs(); +#endif + // If we have urls specified beforehand (i.e. from command line) use them // and nothing else. if (!startup_urls->empty()) diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index ff1d17d..f8cbfd1 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -451,7 +451,6 @@ int BrowserMain(const MainFunctionParams& parameters) { views::ViewsDelegate::views_delegate = new ChromeViewsDelegate; #endif - if (is_first_run) { #if defined(OS_WIN) // During first run we read the google_update registry key to find what @@ -901,8 +900,20 @@ int BrowserMain(const MainFunctionParams& parameters) { MessageLoopForUI::current()->PostTask(FROM_HERE, parameters.ui_task); RunUIMessageLoop(browser_process.get()); } else { - // We are in regular browser boot sequence. Open initial stabs and enter - // the main message loop. + // We are in regular browser boot sequence. +#if defined(OS_MACOSX) + // On Mac, the message which provides the browser with the startup URLs and + // the Apple Event which generates |-applicationDidFinishLaunching:| are + // queued up. + // TODO(viettrungluu): This is what seems to happen *AFAICT*. This is a bit + // fragile. The DCHECK() below will fail if |-aDFL:| is not reached, but + // there is currently no way to tell if subsequent messages are processed. + // This is evidently fragile, and should be made more robust. + MessageLoopForUI::current()->RunAllPending(); + DCHECK(Platform::IsStartupComplete()); +#endif + + // Open initial tabs and enter the main message loop. if (browser_init.Start(parsed_command_line, std::wstring(), profile, &result_code)) { // Call Recycle() here as late as possible, before going into the loop diff --git a/chrome/browser/browser_main.h b/chrome/browser/browser_main.h index 44bc6ab..5f675dd 100644 --- a/chrome/browser/browser_main.h +++ b/chrome/browser/browser_main.h @@ -7,6 +7,11 @@ #include "build/build_config.h" +#if defined(OS_MACOSX) +#include <vector> +class GURL; +#endif + struct MainFunctionParams; class MetricsService; @@ -26,6 +31,23 @@ void DidEndMainMessageLoop(); // are registered with the UMA metrics service. void RecordBreakpadStatusUMA(MetricsService* metrics); +#if defined(OS_MACOSX) +// On Mac, files/URLs to open at startup aren't typically provided on the +// command line, but rather by Launch Services via an Apple Event. We spin a UI +// message loop early to catch this event in the app controller and store the +// URLs. + +// Has the app controller been told that it is done? (I.e., has it received +// |-applicationDidFinishLaunching:|?) +bool IsStartupComplete(); + +// The following functions retrieves the URLs and clears the list of URLs, +// respectively. +const std::vector<GURL>& GetStartupURLs(); +void ClearStartupURLs(); + +#endif + } // namespace Platform #endif // CHROME_BROWSER_BROWSER_MAIN_H_ diff --git a/chrome/browser/browser_main_mac.mm b/chrome/browser/browser_main_mac.mm index f325713..85351db 100644 --- a/chrome/browser/browser_main_mac.mm +++ b/chrome/browser/browser_main_mac.mm @@ -62,6 +62,24 @@ void RecordBreakpadStatusUMA(MetricsService* metrics) { metrics->RecordBreakpadHasDebugger(DebugUtil::BeingDebugged()); } +bool IsStartupComplete() { + AppController* appController = [NSApp delegate]; + DCHECK(appController); + return static_cast<bool>([appController startupComplete]); +} + +const std::vector<GURL>& GetStartupURLs() { + AppController* appController = [NSApp delegate]; + DCHECK(appController); + return [appController startupURLs]; +} + +void ClearStartupURLs() { + AppController* appController = [NSApp delegate]; + DCHECK(appController); + [appController clearStartupURLs]; +} + } // namespace Platform // From browser_main_win.h, stubs until we figure out the right thing... |