diff options
-rw-r--r-- | chrome/app/chrome_command_ids.h | 3 | ||||
-rw-r--r-- | chrome/browser/app_controller_mac.mm | 64 | ||||
-rw-r--r-- | chrome/browser/app_controller_mac_unittest.mm | 2 | ||||
-rw-r--r-- | chrome/browser/background_application_list_model.cc | 11 |
4 files changed, 73 insertions, 7 deletions
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index dccebfa..926088d 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h @@ -5,6 +5,9 @@ // This file lists all the command IDs understood by e.g. the browser. // It is used by Windows RC files, Mac NIB files, and other platforms too. +// Values below IDC_MinimumLabelValue are reserved for dynamic menu items. +#define IDC_MinimumLabelValue 4000 + #define IDC_Messages 4000 #define IDC_MessagesAll 4007 #define IDC_MessagesNone 4008 diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index c25cdff..428f375 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm @@ -14,6 +14,7 @@ #include "base/string_number_conversions.h" #include "base/sys_string_conversions.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/background_application_list_model.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/browser_thread.h" @@ -154,6 +155,7 @@ void RecordLastRunAppBundlePath() { - (void)showPreferencesWindow:(id)sender page:(OptionsPage)page profile:(Profile*)profile; +- (void)executeApplication:(id)sender; @end @implementation AppController @@ -792,7 +794,7 @@ void RecordLastRunAppBundlePath() { enable = YES; } else if (action == @selector(orderFrontStandardAboutPanel:)) { enable = YES; - } else if (action == @selector(newWindowFromDock:)) { + } else if (action == @selector(commandFromDock:)) { enable = YES; } return enable; @@ -928,7 +930,30 @@ void RecordLastRunAppBundlePath() { case IDC_OPTIONS: [self showPreferences:sender]; break; + default: + // Background Applications use dynamic values that must be less than the + // smallest value among the predefined IDC_* labels. + if ([sender tag] < IDC_MinimumLabelValue) + [self executeApplication:sender]; + break; + } +} + +// Run a (background) application in a new tab. +- (void)executeApplication:(id)sender { + NSInteger tag = [sender tag]; + Profile* profile = [self defaultProfile]; + DCHECK(profile); + BackgroundApplicationListModel applications(profile); + DCHECK(tag >= 0 && + tag < static_cast<int>(applications.size())); + Browser* browser = BrowserList::GetLastActive(); + if (!browser) { + Browser::OpenEmptyWindow(profile); + browser = BrowserList::GetLastActive(); } + const Extension* extension = applications.GetExtension(tag); + browser->OpenApplicationTab(profile, extension, NULL); } // Same as |-commandDispatch:|, but executes commands using a disposition @@ -1162,25 +1187,52 @@ void RecordLastRunAppBundlePath() { } // Explicitly bring to the foreground when creating new windows from the dock. -- (void)newWindowFromDock:(id)sender { +- (void)commandFromDock:(id)sender { [NSApp activateIgnoringOtherApps:YES]; [self commandDispatch:sender]; } - (NSMenu*)applicationDockMenu:(NSApplication*)sender { NSMenu* dockMenu = [[[NSMenu alloc] initWithTitle: @""] autorelease]; + Profile* profile = [self defaultProfile]; + + // TODO(rickcam): Mock out BackgroundApplicationListModel, then add unit + // tests which use the mock in place of the profile-initialized model. + + // Avoid breaking unit tests which have no profile. + if (profile) { + int position = 0; + BackgroundApplicationListModel applications(profile); + for (ExtensionList::const_iterator cursor = applications.begin(); + cursor != applications.end(); + ++cursor, ++position) { + DCHECK(position == applications.GetPosition(*cursor)); + scoped_nsobject<NSMenuItem> appItem([[NSMenuItem alloc] + initWithTitle:base::SysUTF16ToNSString(UTF8ToUTF16((*cursor)->name())) + action:@selector(commandFromDock:) + keyEquivalent:@""]); + [appItem setTarget:self]; + [appItem setTag:position]; + [dockMenu addItem:appItem]; + } + if (applications.begin() != applications.end()) { + NSMenuItem* sepItem = [[NSMenuItem separatorItem] init]; + [dockMenu addItem:sepItem]; + } + } + NSString* titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_WINDOW_MAC); scoped_nsobject<NSMenuItem> item([[NSMenuItem alloc] - initWithTitle:titleStr - action:@selector(newWindowFromDock:) - keyEquivalent:@""]); + initWithTitle:titleStr + action:@selector(commandFromDock:) + keyEquivalent:@""]); [item setTarget:self]; [item setTag:IDC_NEW_WINDOW]; [dockMenu addItem:item]; titleStr = l10n_util::GetNSStringWithFixup(IDS_NEW_INCOGNITO_WINDOW_MAC); item.reset([[NSMenuItem alloc] initWithTitle:titleStr - action:@selector(newWindowFromDock:) + action:@selector(commandFromDock:) keyEquivalent:@""]); [item setTarget:self]; [item setTag:IDC_NEW_INCOGNITO_WINDOW]; diff --git a/chrome/browser/app_controller_mac_unittest.mm b/chrome/browser/app_controller_mac_unittest.mm index 6af8e13..88e8de3 100644 --- a/chrome/browser/app_controller_mac_unittest.mm +++ b/chrome/browser/app_controller_mac_unittest.mm @@ -22,6 +22,6 @@ TEST_F(AppControllerTest, DockMenu) { EXPECT_NE(-1, [menu indexOfItemWithTag:IDC_NEW_INCOGNITO_WINDOW]); for (item in [menu itemArray]) { EXPECT_EQ(ac.get(), [item target]); - EXPECT_EQ(@selector(newWindowFromDock:), [item action]); + EXPECT_EQ(@selector(commandFromDock:), [item action]); } } diff --git a/chrome/browser/background_application_list_model.cc b/chrome/browser/background_application_list_model.cc index 4a2a617..eac2577 100644 --- a/chrome/browser/background_application_list_model.cc +++ b/chrome/browser/background_application_list_model.cc @@ -10,6 +10,7 @@ #include "app/l10n_util_collator.h" #include "base/stl_util-inl.h" #include "base/utf_string_conversions.h" +#include "chrome/app/chrome_command_ids.h" #include "chrome/browser/background_mode_manager.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_prefs.h" @@ -157,6 +158,9 @@ BackgroundApplicationListModel::BackgroundApplicationListModel(Profile* profile) registrar_.Add(this, NotificationType::EXTENSIONS_READY, Source<Profile>(profile)); + ExtensionService* service = profile->GetExtensionService(); + if (service && service->is_ready()) + Update(); } void BackgroundApplicationListModel::AddObserver(Observer* observer) { @@ -168,6 +172,13 @@ void BackgroundApplicationListModel::AssociateApplicationData( DCHECK(IsBackgroundApp(*extension)); Application* application = FindApplication(extension); if (!application) { + // App position is used as a dynamic command and so must be less than any + // predefined command id. + if (applications_.size() >= IDC_MinimumLabelValue) { + LOG(ERROR) << "Background application limit of " << IDC_MinimumLabelValue + << " exceeded. Ignoring."; + return; + } application = new Application(this, extension); applications_[extension->id()] = application; application->RequestIcon(Extension::EXTENSION_ICON_BITTY); |