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

Side by Side Diff: chrome/browser/cocoa/extensions/extension_action_context_menu.mm

Issue 525098: [Mac] Implements context menus for Page Actions. Introduces a reusable subcla... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Final changes before submit. Created 10 years, 11 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 #import "chrome/browser/cocoa/extensions/extension_action_context_menu.h"
6
7 #include "app/l10n_util_mac.h"
8 #include "base/sys_string_conversions.h"
9 #include "base/task.h"
10 #include "chrome/browser/browser_list.h"
11 #include "chrome/browser/extensions/extension_install_ui.h"
12 #include "chrome/browser/extensions/extensions_service.h"
13 #include "chrome/browser/profile.h"
14 #include "chrome/common/extensions/extension.h"
15 #include "chrome/common/extensions/extension_constants.h"
16 #include "chrome/common/url_constants.h"
17 #include "grit/generated_resources.h"
18
19 // A class that loads the extension icon on the I/O thread before showing the
20 // confirmation dialog to uninstall the given extension.
21 // Also acts as the extension's UI delegate in order to display the dialog.
22 class AsyncUninstaller : public base::RefCountedThreadSafe<AsyncUninstaller>,
23 public ExtensionInstallUI::Delegate {
24 public:
25 AsyncUninstaller(Extension* extension) : extension_(extension) {}
26
27 // Load the uninstall icon then show the confirmation dialog when finished.
28 void LoadExtensionIconThenConfirmUninstall() {
29 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE,
30 NewRunnableMethod(this, &AsyncUninstaller::LoadIconOnFileThread,
31 &uninstall_icon_));
32 }
33
34 void Cancel() {
35 uninstall_icon_.reset();
36 extension_ = NULL;
37 }
38
39 // Overridden by ExtensionInstallUI::Delegate.
40 virtual void InstallUIProceed() {
41 Browser* browser = BrowserList::GetLastActive();
42 // GetLastActive() returns NULL during testing.
43 if (!browser)
44 return;
45 browser->profile()->GetExtensionsService()->
46 UninstallExtension(extension_->id(), false);
47 }
48
49 virtual void InstallUIAbort() {}
50
51 private:
52 friend class base::RefCountedThreadSafe<AsyncUninstaller>;
53 ~AsyncUninstaller() {}
54
55 void LoadIconOnFileThread(scoped_ptr<SkBitmap>* uninstall_icon) {
56 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
57 Extension::DecodeIcon(extension_, Extension::EXTENSION_ICON_LARGE,
58 uninstall_icon);
59 ChromeThread::PostTask(ChromeThread::UI, FROM_HERE,
60 NewRunnableMethod(this, &AsyncUninstaller::ShowConfirmationDialog,
61 uninstall_icon));
62 }
63
64 void ShowConfirmationDialog(scoped_ptr<SkBitmap>* uninstall_icon) {
65 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
66 // If |extension_| is NULL, then the action was cancelled. Bail.
67 if (!extension_)
68 return;
69
70 Browser* browser = BrowserList::GetLastActive();
71 // GetLastActive() returns NULL during testing.
72 if (!browser)
73 return;
74
75 ExtensionInstallUI client(browser->profile());
76 client.ConfirmUninstall(this, extension_, uninstall_icon->get());
77 }
78
79 // The extension that we're loading the icon for. Weak.
80 Extension* extension_;
81
82 // The uninstall icon shown by the confirmation dialog.
83 scoped_ptr<SkBitmap> uninstall_icon_;
84
85 DISALLOW_COPY_AND_ASSIGN(AsyncUninstaller);
86 };
87
88 @interface ExtensionActionContextMenu(Private)
89 // Callback for the context menu items.
90 - (void)dispatch:(id)menuItem;
91 @end
92
93 @implementation ExtensionActionContextMenu
94
95 namespace {
96 // Enum of menu item choices to their respective indices.
97 // NOTE: You MUST keep this in sync with the |menuItems| NSArray below.
98 enum {
99 kExtensionContextName = 0,
100 kExtensionContextOptions = 2,
101 kExtensionContextDisable = 3,
102 kExtensionContextUninstall = 4,
103 kExtensionContextManage = 6
104 };
105 } // namespace
106
107 - (id)initWithExtension:(Extension*)extension {
108 if ((self = [super initWithTitle:@""])) {
109 extension_ = extension;
110
111 NSArray* menuItems = [NSArray arrayWithObjects:
112 base::SysUTF8ToNSString(extension->name()),
113 [NSMenuItem separatorItem],
114 l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_OPTIONS),
115 l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_DISABLE),
116 l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_UNINSTALL),
117 [NSMenuItem separatorItem],
118 l10n_util::GetNSStringWithFixup(IDS_MANAGE_EXTENSIONS),
119 nil];
120
121 for (id item in menuItems) {
122 if ([item isKindOfClass:[NSMenuItem class]]) {
123 [self addItem:item];
124 } else if ([item isKindOfClass:[NSString class]]) {
125 NSMenuItem* itemObj = [self addItemWithTitle:item
126 action:@selector(dispatch:)
127 keyEquivalent:@""];
128 // The tag should correspond to the enum above.
129 // NOTE: The enum and the order of the menu items MUST be in sync.
130 [itemObj setTag:[self indexOfItem:itemObj]];
131
132 // Disable the 'Options' item if there are no options to set.
133 if ([itemObj tag] == kExtensionContextOptions &&
134 extension_->options_url().spec().length() <= 0) {
135 // Setting the target to nil will disable the item. For some reason
136 // setDisabled:NO does not work.
137 [itemObj setTarget:nil];
138 } else {
139 [itemObj setTarget:self];
140 }
141 }
142 }
143
144 return self;
145 }
146 return nil;
147 }
148
149 - (void)dispatch:(id)menuItem {
150 Browser* browser = BrowserList::GetLastActive();
151 // GetLastActive() returns NULL during testing.
152 if (!browser)
153 return;
154
155 Profile* profile = browser->profile();
156
157 NSMenuItem* item = (NSMenuItem*)menuItem;
158 switch ([item tag]) {
159 case kExtensionContextName: {
160 GURL url(std::string(extension_urls::kGalleryBrowsePrefix) +
161 std::string("/detail/") + extension_->id());
162 browser->OpenURL(url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
163 break;
164 }
165 case kExtensionContextOptions: {
166 DCHECK(!extension_->options_url().is_empty());
167 browser->OpenURL(extension_->options_url(), GURL(),
168 NEW_FOREGROUND_TAB, PageTransition::LINK);
169 break;
170 }
171 case kExtensionContextDisable: {
172 ExtensionsService* extension_service = profile->GetExtensionsService();
173 extension_service->DisableExtension(extension_->id());
174 break;
175 }
176 case kExtensionContextUninstall: {
177 if (uninstaller_.get())
178 uninstaller_->Cancel();
179
180 uninstaller_ = new AsyncUninstaller(extension_);
181 uninstaller_->LoadExtensionIconThenConfirmUninstall();
182 break;
183 }
184 case kExtensionContextManage: {
185 browser->OpenURL(GURL(chrome::kChromeUIExtensionsURL), GURL(),
186 NEW_FOREGROUND_TAB, PageTransition::LINK);
187 break;
188 }
189 default:
190 NOTREACHED();
191 break;
192 }
193 }
194
195 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/extensions/extension_action_context_menu.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698