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

Side by Side Diff: chrome/browser/extensions/external_install_ui.cc

Issue 145153002: Make sideloaded (externally installed) extensions display webstore info (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/external_install_ui.h" 5 #include "chrome/browser/extensions/external_install_ui.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
11 #include "base/memory/ref_counted.h" 11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/app/chrome_command_ids.h" 16 #include "chrome/app/chrome_command_ids.h"
17 #include "chrome/browser/chrome_notification_types.h" 17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/extensions/extension_install_prompt.h" 18 #include "chrome/browser/extensions/extension_install_prompt.h"
19 #include "chrome/browser/extensions/extension_install_ui.h" 19 #include "chrome/browser/extensions/extension_install_ui.h"
20 #include "chrome/browser/extensions/extension_service.h" 20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_uninstall_dialog.h" 21 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
22 #include "chrome/browser/extensions/webstore_data_fetcher.h"
23 #include "chrome/browser/extensions/webstore_data_fetcher_delegate.h"
22 #include "chrome/browser/profiles/profile.h" 24 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/browser.h" 25 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_finder.h" 26 #include "chrome/browser/ui/browser_finder.h"
25 #include "chrome/browser/ui/global_error/global_error.h" 27 #include "chrome/browser/ui/global_error/global_error.h"
26 #include "chrome/browser/ui/global_error/global_error_service.h" 28 #include "chrome/browser/ui/global_error/global_error_service.h"
27 #include "chrome/browser/ui/global_error/global_error_service_factory.h" 29 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
28 #include "chrome/browser/ui/host_desktop.h" 30 #include "chrome/browser/ui/host_desktop.h"
29 #include "chrome/common/extensions/extension_constants.h" 31 #include "chrome/common/extensions/extension_constants.h"
30 #include "chrome/common/extensions/manifest_url_handler.h" 32 #include "chrome/common/extensions/manifest_url_handler.h"
31 #include "content/public/browser/notification_details.h" 33 #include "content/public/browser/notification_details.h"
(...skipping 17 matching lines...) Expand all
49 bool UseBubbleInstall(const Extension* extension, bool is_new_profile) { 51 bool UseBubbleInstall(const Extension* extension, bool is_new_profile) {
50 return ManifestURL::UpdatesFromGallery(extension) && !is_new_profile; 52 return ManifestURL::UpdatesFromGallery(extension) && !is_new_profile;
51 } 53 }
52 54
53 } // namespace 55 } // namespace
54 56
55 static const int kMenuCommandId = IDC_EXTERNAL_EXTENSION_ALERT; 57 static const int kMenuCommandId = IDC_EXTERNAL_EXTENSION_ALERT;
56 58
57 class ExternalInstallGlobalError; 59 class ExternalInstallGlobalError;
58 60
59 // TODO(mpcomplete): Get rid of the refcounting on this class, or document 61 // This class is refcounted to stay alive while we try and pull webstore data.
60 // why it's necessary. Will do after refactoring to merge back with
61 // ExtensionDisabledDialogDelegate.
62 class ExternalInstallDialogDelegate 62 class ExternalInstallDialogDelegate
63 : public ExtensionInstallPrompt::Delegate, 63 : public ExtensionInstallPrompt::Delegate,
64 public WebstoreDataFetcherDelegate,
64 public base::RefCountedThreadSafe<ExternalInstallDialogDelegate> { 65 public base::RefCountedThreadSafe<ExternalInstallDialogDelegate> {
65 public: 66 public:
66 ExternalInstallDialogDelegate(Browser* browser, 67 ExternalInstallDialogDelegate(Browser* browser,
67 ExtensionService* service, 68 ExtensionService* service,
68 const Extension* extension, 69 const Extension* extension,
69 bool use_global_error); 70 bool use_global_error);
70 71
71 Browser* browser() { return browser_; } 72 Browser* browser() { return browser_; }
72 73
73 private: 74 private:
74 friend class base::RefCountedThreadSafe<ExternalInstallDialogDelegate>; 75 friend class base::RefCountedThreadSafe<ExternalInstallDialogDelegate>;
75 friend class ExternalInstallGlobalError; 76 friend class ExternalInstallGlobalError;
76 77
77 virtual ~ExternalInstallDialogDelegate(); 78 virtual ~ExternalInstallDialogDelegate();
78 79
79 // ExtensionInstallPrompt::Delegate: 80 // ExtensionInstallPrompt::Delegate:
80 virtual void InstallUIProceed() OVERRIDE; 81 virtual void InstallUIProceed() OVERRIDE;
81 virtual void InstallUIAbort(bool user_initiated) OVERRIDE; 82 virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
82 83
84 // WebstoreDataFetcherDelegate:
85 virtual void OnWebstoreRequestFailure() OVERRIDE;
86 virtual void OnWebstoreResponseParseSuccess(
87 scoped_ptr<base::DictionaryValue> webstore_data) OVERRIDE;
88 virtual void OnWebstoreResponseParseFailure(
89 const std::string& error) OVERRIDE;
90
91 // Show the install dialog to the user.
92 void ShowInstallUI();
93
83 // The UI for showing the install dialog when enabling. 94 // The UI for showing the install dialog when enabling.
84 scoped_ptr<ExtensionInstallPrompt> install_ui_; 95 scoped_ptr<ExtensionInstallPrompt> install_ui_;
96 scoped_ptr<ExtensionInstallPrompt::Prompt> prompt_;
85 97
86 Browser* browser_; 98 Browser* browser_;
87 base::WeakPtr<ExtensionService> service_weak_; 99 base::WeakPtr<ExtensionService> service_weak_;
88 const std::string extension_id_; 100 scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher_;
101 const Extension* extension_;
102 bool use_global_error_;
103
104 DISALLOW_COPY_AND_ASSIGN(ExternalInstallDialogDelegate);
89 }; 105 };
90 106
91 // Only shows a menu item, no bubble. Clicking the menu item shows 107 // Only shows a menu item, no bubble. Clicking the menu item shows
92 // an external install dialog. 108 // an external install dialog.
93 class ExternalInstallMenuAlert : public GlobalErrorWithStandardBubble, 109 class ExternalInstallMenuAlert : public GlobalErrorWithStandardBubble,
94 public content::NotificationObserver { 110 public content::NotificationObserver {
95 public: 111 public:
96 ExternalInstallMenuAlert(ExtensionService* service, 112 ExternalInstallMenuAlert(ExtensionService* service,
97 const Extension* extension); 113 const Extension* extension);
98 virtual ~ExternalInstallMenuAlert(); 114 virtual ~ExternalInstallMenuAlert();
(...skipping 17 matching lines...) Expand all
116 132
117 // content::NotificationObserver implementation. 133 // content::NotificationObserver implementation.
118 virtual void Observe(int type, 134 virtual void Observe(int type,
119 const content::NotificationSource& source, 135 const content::NotificationSource& source,
120 const content::NotificationDetails& details) OVERRIDE; 136 const content::NotificationDetails& details) OVERRIDE;
121 137
122 protected: 138 protected:
123 ExtensionService* service_; 139 ExtensionService* service_;
124 const Extension* extension_; 140 const Extension* extension_;
125 content::NotificationRegistrar registrar_; 141 content::NotificationRegistrar registrar_;
142
143 private:
144 DISALLOW_COPY_AND_ASSIGN(ExternalInstallMenuAlert);
126 }; 145 };
127 146
128 // Shows a menu item and a global error bubble, replacing the install dialog. 147 // Shows a menu item and a global error bubble, replacing the install dialog.
129 class ExternalInstallGlobalError : public ExternalInstallMenuAlert { 148 class ExternalInstallGlobalError : public ExternalInstallMenuAlert {
130 public: 149 public:
131 ExternalInstallGlobalError(ExtensionService* service, 150 ExternalInstallGlobalError(ExtensionService* service,
132 const Extension* extension, 151 const Extension* extension,
133 ExternalInstallDialogDelegate* delegate, 152 ExternalInstallDialogDelegate* delegate,
134 const ExtensionInstallPrompt::Prompt& prompt); 153 const ExtensionInstallPrompt::Prompt& prompt);
135 virtual ~ExternalInstallGlobalError(); 154 virtual ~ExternalInstallGlobalError();
136 155
137 virtual void ExecuteMenuItem(Browser* browser) OVERRIDE; 156 virtual void ExecuteMenuItem(Browser* browser) OVERRIDE;
138 virtual bool HasBubbleView() OVERRIDE; 157 virtual bool HasBubbleView() OVERRIDE;
139 virtual gfx::Image GetBubbleViewIcon() OVERRIDE; 158 virtual gfx::Image GetBubbleViewIcon() OVERRIDE;
140 virtual base::string16 GetBubbleViewTitle() OVERRIDE; 159 virtual base::string16 GetBubbleViewTitle() OVERRIDE;
141 virtual std::vector<base::string16> GetBubbleViewMessages() OVERRIDE; 160 virtual std::vector<base::string16> GetBubbleViewMessages() OVERRIDE;
142 virtual base::string16 GetBubbleViewAcceptButtonLabel() OVERRIDE; 161 virtual base::string16 GetBubbleViewAcceptButtonLabel() OVERRIDE;
143 virtual base::string16 GetBubbleViewCancelButtonLabel() OVERRIDE; 162 virtual base::string16 GetBubbleViewCancelButtonLabel() OVERRIDE;
144 virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE; 163 virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE;
145 virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE; 164 virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE;
146 virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE; 165 virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE;
147 166
148 protected: 167 protected:
149 // Ref-counted, but needs to be disposed of if we are dismissed without 168 // Ref-counted, but needs to be disposed of if we are dismissed without
150 // having been clicked (perhaps because the user enabled the extension 169 // having been clicked (perhaps because the user enabled the extension
151 // manually). 170 // manually).
152 ExternalInstallDialogDelegate* delegate_; 171 ExternalInstallDialogDelegate* delegate_;
153 const ExtensionInstallPrompt::Prompt* prompt_; 172 const ExtensionInstallPrompt::Prompt* prompt_;
173
174 private:
175 DISALLOW_COPY_AND_ASSIGN(ExternalInstallGlobalError);
154 }; 176 };
155 177
156 static void CreateExternalInstallGlobalError( 178 static void CreateExternalInstallGlobalError(
157 base::WeakPtr<ExtensionService> service, 179 base::WeakPtr<ExtensionService> service,
158 const std::string& extension_id, 180 const std::string& extension_id,
159 const ExtensionInstallPrompt::ShowParams& show_params, 181 const ExtensionInstallPrompt::ShowParams& show_params,
160 ExtensionInstallPrompt::Delegate* prompt_delegate, 182 ExtensionInstallPrompt::Delegate* prompt_delegate,
161 const ExtensionInstallPrompt::Prompt& prompt) { 183 const ExtensionInstallPrompt::Prompt& prompt) {
162 if (!service.get()) 184 if (!service.get())
163 return; 185 return;
(...skipping 25 matching lines...) Expand all
189 211
190 // ExternalInstallDialogDelegate -------------------------------------------- 212 // ExternalInstallDialogDelegate --------------------------------------------
191 213
192 ExternalInstallDialogDelegate::ExternalInstallDialogDelegate( 214 ExternalInstallDialogDelegate::ExternalInstallDialogDelegate(
193 Browser* browser, 215 Browser* browser,
194 ExtensionService* service, 216 ExtensionService* service,
195 const Extension* extension, 217 const Extension* extension,
196 bool use_global_error) 218 bool use_global_error)
197 : browser_(browser), 219 : browser_(browser),
198 service_weak_(service->AsWeakPtr()), 220 service_weak_(service->AsWeakPtr()),
199 extension_id_(extension->id()) { 221 extension_(extension),
222 use_global_error_(use_global_error) {
200 AddRef(); // Balanced in Proceed or Abort. 223 AddRef(); // Balanced in Proceed or Abort.
201 224
225 prompt_.reset(new ExtensionInstallPrompt::Prompt(
226 ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT));
227
228 // If we don't have a browser, we can't go to the webstore to fetch data.
Finnur 2014/01/24 11:38:31 Does this ever happen?
Devlin 2014/01/24 18:10:24 TL;DR: Yes, but usually only in tests. It can, th
Finnur 2014/01/27 13:41:04 It is certainly not unheard of to have these thing
Devlin 2014/01/27 18:15:21 Done.
229 if (!browser) {
230 ShowInstallUI();
231 return;
232 }
233
234 webstore_data_fetcher_.reset(new WebstoreDataFetcher(
235 this,
236 browser->profile()->GetRequestContext(),
237 GURL::EmptyGURL(),
238 extension->id()));
239 webstore_data_fetcher_->Start();
240 }
241
242 void ExternalInstallDialogDelegate::OnWebstoreRequestFailure() {
243 ShowInstallUI();
244 }
245
246 void ExternalInstallDialogDelegate::OnWebstoreResponseParseSuccess(
247 scoped_ptr<base::DictionaryValue> webstore_data) {
248 std::string localized_user_count;
249 double average_rating;
250 int rating_count;
251 if (!webstore_data->GetString(kUsersKey, &localized_user_count) ||
252 !webstore_data->GetDouble(kAverageRatingKey, &average_rating) ||
253 !webstore_data->GetInteger(kRatingCountKey, &rating_count)) {
254 // If we don't get a valid webstore response, short circuit, and continue
255 // to show a prompt without webstore data.
256 ShowInstallUI();
257 return;
258 }
259
260 bool show_user_count = true;
261 webstore_data->GetBoolean(kShowUserCountKey, &show_user_count);
262
263 prompt_->SetWebstoreData(localized_user_count,
264 show_user_count,
265 average_rating,
266 rating_count);
267
268 ShowInstallUI();
269 }
270
271 void ExternalInstallDialogDelegate::OnWebstoreResponseParseFailure(
272 const std::string& error) {
273 ShowInstallUI();
274 }
275
276 void ExternalInstallDialogDelegate::ShowInstallUI() {
202 install_ui_.reset( 277 install_ui_.reset(
203 ExtensionInstallUI::CreateInstallPromptWithBrowser(browser)); 278 ExtensionInstallUI::CreateInstallPromptWithBrowser(browser_));
204 279
205 const ExtensionInstallPrompt::ShowDialogCallback callback = 280 const ExtensionInstallPrompt::ShowDialogCallback callback =
206 use_global_error ? 281 use_global_error_ ?
207 base::Bind(&CreateExternalInstallGlobalError, 282 base::Bind(&CreateExternalInstallGlobalError,
208 service_weak_, extension_id_) : 283 service_weak_,
209 ExtensionInstallPrompt::GetDefaultShowDialogCallback(); 284 extension_->id()) :
210 install_ui_->ConfirmExternalInstall(this, extension, callback); 285 ExtensionInstallPrompt::GetDefaultShowDialogCallback();
286
287 install_ui_->ConfirmExternalInstall(this, extension_, callback, *prompt_);
211 } 288 }
212 289
213 ExternalInstallDialogDelegate::~ExternalInstallDialogDelegate() { 290 ExternalInstallDialogDelegate::~ExternalInstallDialogDelegate() {
214 } 291 }
215 292
216 void ExternalInstallDialogDelegate::InstallUIProceed() { 293 void ExternalInstallDialogDelegate::InstallUIProceed() {
217 if (!service_weak_.get()) 294 if (!service_weak_.get())
218 return; 295 return;
219 const Extension* extension = 296 const Extension* extension =
220 service_weak_->GetInstalledExtension(extension_id_); 297 service_weak_->GetInstalledExtension(extension_->id());
221 if (!extension) 298 if (!extension)
222 return; 299 return;
223 service_weak_->GrantPermissionsAndEnableExtension(extension); 300 service_weak_->GrantPermissionsAndEnableExtension(extension);
224 Release(); 301 Release();
225 } 302 }
226 303
227 void ExternalInstallDialogDelegate::InstallUIAbort(bool user_initiated) { 304 void ExternalInstallDialogDelegate::InstallUIAbort(bool user_initiated) {
228 if (!service_weak_.get()) 305 if (!service_weak_.get())
229 return; 306 return;
230 const Extension* extension = 307 service_weak_->UninstallExtension(extension_->id(), false, NULL);
231 service_weak_->GetInstalledExtension(extension_id_);
232 if (!extension)
233 return;
Finnur 2014/01/24 11:38:31 Tread carefully here. https://code.google.com/p/ch
Yoyo Zhou 2014/01/24 23:12:57 Yeah, I don't remember the exact scenario, but it'
Devlin 2014/01/27 18:15:21 Done.
234 service_weak_->UninstallExtension(extension_id_, false, NULL);
235 Release(); 308 Release();
236 } 309 }
237 310
238 // ExternalInstallMenuAlert ------------------------------------------------- 311 // ExternalInstallMenuAlert -------------------------------------------------
239 312
240 ExternalInstallMenuAlert::ExternalInstallMenuAlert( 313 ExternalInstallMenuAlert::ExternalInstallMenuAlert(
241 ExtensionService* service, 314 ExtensionService* service,
242 const Extension* extension) 315 const Extension* extension)
243 : service_(service), 316 : service_(service),
244 extension_(extension) { 317 extension_(extension) {
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 527
455 bool HasExternalInstallBubble(ExtensionService* service) { 528 bool HasExternalInstallBubble(ExtensionService* service) {
456 GlobalErrorService* error_service = 529 GlobalErrorService* error_service =
457 GlobalErrorServiceFactory::GetForProfile(service->profile()); 530 GlobalErrorServiceFactory::GetForProfile(service->profile());
458 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID( 531 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID(
459 kMenuCommandId); 532 kMenuCommandId);
460 return error && error->HasBubbleView(); 533 return error && error->HasBubbleView();
461 } 534 }
462 535
463 } // namespace extensions 536 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698