Index: chrome/browser/cocoa/extensions/extension_action_context_menu.mm |
=================================================================== |
--- chrome/browser/cocoa/extensions/extension_action_context_menu.mm (revision 0) |
+++ chrome/browser/cocoa/extensions/extension_action_context_menu.mm (revision 0) |
@@ -0,0 +1,195 @@ |
+// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "chrome/browser/cocoa/extensions/extension_action_context_menu.h" |
+ |
+#include "app/l10n_util_mac.h" |
+#include "base/sys_string_conversions.h" |
+#include "base/task.h" |
+#include "chrome/browser/browser_list.h" |
+#include "chrome/browser/extensions/extension_install_ui.h" |
+#include "chrome/browser/extensions/extensions_service.h" |
+#include "chrome/browser/profile.h" |
+#include "chrome/common/extensions/extension.h" |
+#include "chrome/common/extensions/extension_constants.h" |
+#include "chrome/common/url_constants.h" |
+#include "grit/generated_resources.h" |
+ |
+// A class that loads the extension icon on the I/O thread before showing the |
+// confirmation dialog to uninstall the given extension. |
+// Also acts as the extension's UI delegate in order to display the dialog. |
+class AsyncUninstaller : public base::RefCountedThreadSafe<AsyncUninstaller>, |
+ public ExtensionInstallUI::Delegate { |
+ public: |
+ AsyncUninstaller(Extension* extension) : extension_(extension) {} |
+ |
+ // Load the uninstall icon then show the confirmation dialog when finished. |
+ void LoadExtensionIconThenConfirmUninstall() { |
+ ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, |
+ NewRunnableMethod(this, &AsyncUninstaller::LoadIconOnFileThread, |
+ &uninstall_icon_)); |
+ } |
+ |
+ void Cancel() { |
+ uninstall_icon_.reset(); |
+ extension_ = NULL; |
+ } |
+ |
+ // Overridden by ExtensionInstallUI::Delegate. |
+ virtual void InstallUIProceed() { |
+ Browser* browser = BrowserList::GetLastActive(); |
+ // GetLastActive() returns NULL during testing. |
+ if (!browser) |
+ return; |
+ browser->profile()->GetExtensionsService()-> |
+ UninstallExtension(extension_->id(), false); |
+ } |
+ |
+ virtual void InstallUIAbort() {} |
+ |
+ private: |
+ friend class base::RefCountedThreadSafe<AsyncUninstaller>; |
+ ~AsyncUninstaller() {} |
+ |
+ void LoadIconOnFileThread(scoped_ptr<SkBitmap>* uninstall_icon) { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
+ Extension::DecodeIcon(extension_, Extension::EXTENSION_ICON_LARGE, |
+ uninstall_icon); |
+ ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, |
+ NewRunnableMethod(this, &AsyncUninstaller::ShowConfirmationDialog, |
+ uninstall_icon)); |
+ } |
+ |
+ void ShowConfirmationDialog(scoped_ptr<SkBitmap>* uninstall_icon) { |
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); |
+ // If |extension_| is NULL, then the action was cancelled. Bail. |
+ if (!extension_) |
+ return; |
+ |
+ Browser* browser = BrowserList::GetLastActive(); |
+ // GetLastActive() returns NULL during testing. |
+ if (!browser) |
+ return; |
+ |
+ ExtensionInstallUI client(browser->profile()); |
+ client.ConfirmUninstall(this, extension_, uninstall_icon->get()); |
+ } |
+ |
+ // The extension that we're loading the icon for. Weak. |
+ Extension* extension_; |
+ |
+ // The uninstall icon shown by the confirmation dialog. |
+ scoped_ptr<SkBitmap> uninstall_icon_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AsyncUninstaller); |
+}; |
+ |
+@interface ExtensionActionContextMenu(Private) |
+// Callback for the context menu items. |
+- (void)dispatch:(id)menuItem; |
+@end |
+ |
+@implementation ExtensionActionContextMenu |
+ |
+namespace { |
+// Enum of menu item choices to their respective indices. |
+// NOTE: You MUST keep this in sync with the |menuItems| NSArray below. |
+enum { |
+ kExtensionContextName = 0, |
+ kExtensionContextOptions = 2, |
+ kExtensionContextDisable = 3, |
+ kExtensionContextUninstall = 4, |
+ kExtensionContextManage = 6 |
+}; |
+} // namespace |
+ |
+- (id)initWithExtension:(Extension*)extension { |
+ if ((self = [super initWithTitle:@""])) { |
+ extension_ = extension; |
+ |
+ NSArray* menuItems = [NSArray arrayWithObjects: |
+ base::SysUTF8ToNSString(extension->name()), |
+ [NSMenuItem separatorItem], |
+ l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_OPTIONS), |
+ l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_DISABLE), |
+ l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_UNINSTALL), |
+ [NSMenuItem separatorItem], |
+ l10n_util::GetNSStringWithFixup(IDS_MANAGE_EXTENSIONS), |
+ nil]; |
+ |
+ for (id item in menuItems) { |
+ if ([item isKindOfClass:[NSMenuItem class]]) { |
+ [self addItem:item]; |
+ } else if ([item isKindOfClass:[NSString class]]) { |
+ NSMenuItem* itemObj = [self addItemWithTitle:item |
+ action:@selector(dispatch:) |
+ keyEquivalent:@""]; |
+ // The tag should correspond to the enum above. |
+ // NOTE: The enum and the order of the menu items MUST be in sync. |
+ [itemObj setTag:[self indexOfItem:itemObj]]; |
+ |
+ // Disable the 'Options' item if there are no options to set. |
+ if ([itemObj tag] == kExtensionContextOptions && |
+ extension_->options_url().spec().length() <= 0) { |
+ // Setting the target to nil will disable the item. For some reason |
+ // setDisabled:NO does not work. |
+ [itemObj setTarget:nil]; |
+ } else { |
+ [itemObj setTarget:self]; |
+ } |
+ } |
+ } |
+ |
+ return self; |
+ } |
+ return nil; |
+} |
+ |
+- (void)dispatch:(id)menuItem { |
+ Browser* browser = BrowserList::GetLastActive(); |
+ // GetLastActive() returns NULL during testing. |
+ if (!browser) |
+ return; |
+ |
+ Profile* profile = browser->profile(); |
+ |
+ NSMenuItem* item = (NSMenuItem*)menuItem; |
+ switch ([item tag]) { |
+ case kExtensionContextName: { |
+ GURL url(std::string(extension_urls::kGalleryBrowsePrefix) + |
+ std::string("/detail/") + extension_->id()); |
+ browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); |
+ break; |
+ } |
+ case kExtensionContextOptions: { |
+ DCHECK(!extension_->options_url().is_empty()); |
+ browser->OpenURL(extension_->options_url(), GURL(), |
+ NEW_FOREGROUND_TAB, PageTransition::LINK); |
+ break; |
+ } |
+ case kExtensionContextDisable: { |
+ ExtensionsService* extension_service = profile->GetExtensionsService(); |
+ extension_service->DisableExtension(extension_->id()); |
+ break; |
+ } |
+ case kExtensionContextUninstall: { |
+ if (uninstaller_.get()) |
+ uninstaller_->Cancel(); |
+ |
+ uninstaller_ = new AsyncUninstaller(extension_); |
+ uninstaller_->LoadExtensionIconThenConfirmUninstall(); |
+ break; |
+ } |
+ case kExtensionContextManage: { |
+ browser->OpenURL(GURL(chrome::kChromeUIExtensionsURL), GURL(), |
+ NEW_FOREGROUND_TAB, PageTransition::LINK); |
+ break; |
+ } |
+ default: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+@end |
Property changes on: chrome/browser/cocoa/extensions/extension_action_context_menu.mm |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |