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

Side by Side Diff: chrome/browser/ui/intents/web_intent_picker_controller.cc

Issue 9763001: [Web Intents] Inline installation of extensions in web intents picker. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: mac fix Created 8 years, 9 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
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/ui/intents/web_intent_picker_controller.h" 5 #include "chrome/browser/ui/intents/web_intent_picker_controller.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
11 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/extensions/webstore_installer.h"
12 #include "chrome/browser/favicon/favicon_service.h" 12 #include "chrome/browser/favicon/favicon_service.h"
13 #include "chrome/browser/intents/default_web_intent_service.h" 13 #include "chrome/browser/intents/default_web_intent_service.h"
14 #include "chrome/browser/intents/web_intents_registry_factory.h" 14 #include "chrome/browser/intents/web_intents_registry_factory.h"
15 #include "chrome/browser/intents/cws_intents_registry_factory.h" 15 #include "chrome/browser/intents/cws_intents_registry_factory.h"
16 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/tab_contents/tab_util.h" 17 #include "chrome/browser/tab_contents/tab_util.h"
18 #include "chrome/browser/tabs/tab_strip_model.h" 18 #include "chrome/browser/tabs/tab_strip_model.h"
19 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_list.h" 20 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/browser/ui/browser_navigator.h" 21 #include "chrome/browser/ui/browser_navigator.h"
21 #include "chrome/browser/ui/intents/web_intent_picker.h" 22 #include "chrome/browser/ui/intents/web_intent_picker.h"
22 #include "chrome/browser/ui/intents/web_intent_picker_model.h" 23 #include "chrome/browser/ui/intents/web_intent_picker_model.h"
23 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
24 #include "chrome/browser/webdata/web_data_service.h" 25 #include "chrome/browser/webdata/web_data_service.h"
25 #include "chrome/common/chrome_notification_types.h" 26 #include "chrome/common/chrome_notification_types.h"
26 #include "content/public/browser/browser_thread.h" 27 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/navigation_controller.h"
27 #include "content/public/browser/notification_source.h" 29 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/web_contents.h" 30 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_intents_dispatcher.h" 31 #include "content/public/browser/web_intents_dispatcher.h"
30 #include "content/public/common/url_fetcher.h" 32 #include "content/public/common/url_fetcher.h"
31 #include "content/public/common/url_fetcher_delegate.h" 33 #include "content/public/common/url_fetcher_delegate.h"
32 #include "net/base/load_flags.h" 34 #include "net/base/load_flags.h"
33 #include "skia/ext/image_operations.h" 35 #include "skia/ext/image_operations.h"
34 #include "ui/gfx/codec/png_codec.h" 36 #include "ui/gfx/codec/png_codec.h"
35 #include "ui/gfx/favicon_size.h" 37 #include "ui/gfx/favicon_size.h"
36 #include "ui/gfx/image/image.h" 38 #include "ui/gfx/image/image.h"
(...skipping 22 matching lines...) Expand all
59 case webkit_glue::WebIntentServiceData::DISPOSITION_INLINE: 61 case webkit_glue::WebIntentServiceData::DISPOSITION_INLINE:
60 return WebIntentPickerModel::DISPOSITION_INLINE; 62 return WebIntentPickerModel::DISPOSITION_INLINE;
61 case webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW: 63 case webkit_glue::WebIntentServiceData::DISPOSITION_WINDOW:
62 return WebIntentPickerModel::DISPOSITION_WINDOW; 64 return WebIntentPickerModel::DISPOSITION_WINDOW;
63 default: 65 default:
64 NOTREACHED(); 66 NOTREACHED();
65 return WebIntentPickerModel::DISPOSITION_WINDOW; 67 return WebIntentPickerModel::DISPOSITION_WINDOW;
66 } 68 }
67 } 69 }
68 70
71 // Self-deleting trampoline that forwards a WebIntentsRegistry response to a
72 // callback.
73 class WebIntentsRegistryTrampoline : public WebIntentsRegistry::Consumer {
74 public:
75 typedef std::vector<webkit_glue::WebIntentServiceData> IntentServices;
76 typedef base::Callback<void(const IntentServices&)> ForwardingCallback;
77
78 explicit WebIntentsRegistryTrampoline(const ForwardingCallback& callback);
79 ~WebIntentsRegistryTrampoline();
80
81 // WebIntentsRegistry::Consumer implementation.
82 virtual void OnIntentsQueryDone(
83 WebIntentsRegistry::QueryID,
84 const std::vector<webkit_glue::WebIntentServiceData>& services) OVERRIDE;
85 virtual void OnIntentsDefaultsQueryDone(
86 WebIntentsRegistry::QueryID,
87 const DefaultWebIntentService& default_service) OVERRIDE {}
88
89 private:
90 // Forwarding callback from |OnIntentsQueryDone|.
91 ForwardingCallback callback_;
92 };
93
94 WebIntentsRegistryTrampoline::WebIntentsRegistryTrampoline(
95 const ForwardingCallback& callback)
96 : callback_(callback) {
97 }
98
99 WebIntentsRegistryTrampoline::~WebIntentsRegistryTrampoline() {
100 }
101
102 void WebIntentsRegistryTrampoline::OnIntentsQueryDone(
103 WebIntentsRegistry::QueryID,
104 const std::vector<webkit_glue::WebIntentServiceData>& services) {
105 DCHECK(!callback_.is_null());
106 callback_.Run(services);
107 delete this;
108 }
109
110 // Self-deleting trampoline that forwards A URLFetcher response to a callback.
69 class URLFetcherTrampoline : public content::URLFetcherDelegate { 111 class URLFetcherTrampoline : public content::URLFetcherDelegate {
70 public: 112 public:
71 typedef base::Callback<void(const content::URLFetcher* source)> Callback; 113 typedef base::Callback<void(const content::URLFetcher* source)>
114 ForwardingCallback;
72 115
73 explicit URLFetcherTrampoline(const Callback& callback) 116 explicit URLFetcherTrampoline(const ForwardingCallback& callback);
74 : callback_(callback) {} 117 ~URLFetcherTrampoline();
75 ~URLFetcherTrampoline() {}
76 118
77 // content::URLFetcherDelegate implementation. 119 // content::URLFetcherDelegate implementation.
78 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE { 120 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE;
79 callback_.Run(source);
80 delete source;
81 delete this;
82 }
83 121
84 private: 122 private:
85 Callback callback_; 123 // Fowarding callback from |OnURLFetchComplete|.
124 ForwardingCallback callback_;
86 }; 125 };
87 126
127 URLFetcherTrampoline::URLFetcherTrampoline(const ForwardingCallback& callback)
128 : callback_(callback) {
129 }
130
131 URLFetcherTrampoline::~URLFetcherTrampoline() {
132 }
133
134 void URLFetcherTrampoline::OnURLFetchComplete(
135 const content::URLFetcher* source) {
136 DCHECK(!callback_.is_null());
137 callback_.Run(source);
138 delete source;
139 delete this;
140 }
141
88 } // namespace 142 } // namespace
89 143
90 WebIntentPickerController::WebIntentPickerController( 144 WebIntentPickerController::WebIntentPickerController(
91 TabContentsWrapper* wrapper) 145 TabContentsWrapper* wrapper)
92 : wrapper_(wrapper), 146 : wrapper_(wrapper),
93 picker_(NULL), 147 picker_(NULL),
94 picker_model_(new WebIntentPickerModel()), 148 picker_model_(new WebIntentPickerModel()),
95 pending_async_count_(0), 149 pending_async_count_(0),
96 picker_shown_(false), 150 picker_shown_(false),
97 intents_dispatcher_(NULL), 151 intents_dispatcher_(NULL),
(...skipping 19 matching lines...) Expand all
117 } 171 }
118 172
119 void WebIntentPickerController::ShowDialog(Browser* browser, 173 void WebIntentPickerController::ShowDialog(Browser* browser,
120 const string16& action, 174 const string16& action,
121 const string16& type) { 175 const string16& type) {
122 // Only show a picker once. 176 // Only show a picker once.
123 if (picker_shown_) 177 if (picker_shown_)
124 return; 178 return;
125 179
126 picker_model_->Clear(); 180 picker_model_->Clear();
181 picker_model_->set_action(action);
182 picker_model_->set_mimetype(type);
127 183
128 // If picker is non-NULL, it was set by a test. 184 // If picker is non-NULL, it was set by a test.
129 if (picker_ == NULL) { 185 if (picker_ == NULL) {
130 picker_ = WebIntentPicker::Create(browser, wrapper_, this, 186 picker_ = WebIntentPicker::Create(browser, wrapper_, this,
131 picker_model_.get()); 187 picker_model_.get());
132 } 188 }
133 189
134 picker_shown_ = true; 190 picker_shown_ = true;
135 pending_async_count_+= 2; 191 pending_async_count_+= 2;
136 GetWebIntentsRegistry(wrapper_)->GetIntentServices(action, type, this); 192 GetWebIntentsRegistry(wrapper_)->GetIntentServices(
137 GetCWSIntentsRegistry(wrapper_)->GetIntentServices(action, type, 193 action, type,
194 // WebIntentsRegistryTrampoline is self-deleting.
195 new WebIntentsRegistryTrampoline(
196 base::Bind(&WebIntentPickerController::OnWebIntentServicesAvailable,
197 weak_ptr_factory_.GetWeakPtr())));
198 GetCWSIntentsRegistry(wrapper_)->GetIntentServices(
199 action, type,
138 base::Bind(&WebIntentPickerController::OnCWSIntentServicesAvailable, 200 base::Bind(&WebIntentPickerController::OnCWSIntentServicesAvailable,
139 weak_ptr_factory_.GetWeakPtr())); 201 weak_ptr_factory_.GetWeakPtr()));
140 } 202 }
141 203
142 void WebIntentPickerController::Observe( 204 void WebIntentPickerController::Observe(
143 int type, 205 int type,
144 const content::NotificationSource& source, 206 const content::NotificationSource& source,
145 const content::NotificationDetails& details) { 207 const content::NotificationDetails& details) {
146 DCHECK(type == content::NOTIFICATION_LOAD_START || 208 DCHECK(type == content::NOTIFICATION_LOAD_START ||
147 type == content::NOTIFICATION_TAB_CLOSING); 209 type == content::NOTIFICATION_TAB_CLOSING);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 break; 262 break;
201 } 263 }
202 } 264 }
203 265
204 void WebIntentPickerController::OnInlineDispositionWebContentsCreated( 266 void WebIntentPickerController::OnInlineDispositionWebContentsCreated(
205 content::WebContents* web_contents) { 267 content::WebContents* web_contents) {
206 if (web_contents) 268 if (web_contents)
207 intents_dispatcher_->DispatchIntent(web_contents); 269 intents_dispatcher_->DispatchIntent(web_contents);
208 } 270 }
209 271
272 void WebIntentPickerController::OnExtensionInstallRequested(
273 const std::string& id) {
274 webstore_installer_ = new WebstoreInstaller(
275 wrapper_->profile(), this, &wrapper_->web_contents()->GetController(), id,
276 WebstoreInstaller::FLAG_INLINE_INSTALL);
277
278 pending_async_count_++;
279 webstore_installer_->Start();
280 }
281
210 void WebIntentPickerController::OnCancelled() { 282 void WebIntentPickerController::OnCancelled() {
211 if (!intents_dispatcher_) 283 if (!intents_dispatcher_)
212 return; 284 return;
213 285
214 if (service_tab_) { 286 if (service_tab_) {
215 intents_dispatcher_->SendReplyMessage( 287 intents_dispatcher_->SendReplyMessage(
216 webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED, string16()); 288 webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED, string16());
217 } else { 289 } else {
218 intents_dispatcher_->SendReplyMessage( 290 intents_dispatcher_->SendReplyMessage(
219 webkit_glue::WEB_INTENT_PICKER_CANCELLED, string16()); 291 webkit_glue::WEB_INTENT_PICKER_CANCELLED, string16());
220 } 292 }
221 293
222 ClosePicker(); 294 ClosePicker();
223 } 295 }
224 296
225 void WebIntentPickerController::OnClosing() { 297 void WebIntentPickerController::OnClosing() {
226 picker_shown_ = false; 298 picker_shown_ = false;
227 picker_ = NULL; 299 picker_ = NULL;
228 } 300 }
229 301
302 void WebIntentPickerController::OnExtensionInstallSuccess(
303 const std::string& id) {
304 picker_->OnExtensionInstallSuccess(id);
305 pending_async_count_++;
306 GetWebIntentsRegistry(wrapper_)->GetIntentServicesForExtensionFilter(
307 picker_model_->action(),
308 picker_model_->mimetype(),
309 id,
310 new WebIntentsRegistryTrampoline(
311 base::Bind(
312 &WebIntentPickerController::OnExtensionInstallServiceAvailable,
313 weak_ptr_factory_.GetWeakPtr())));
314 AsyncOperationFinished();
315 }
316
317 void WebIntentPickerController::OnExtensionInstallFailure(
318 const std::string& id,
319 const std::string& error) {
320 picker_->OnExtensionInstallFailure(id);
321 AsyncOperationFinished();
322 }
323
230 void WebIntentPickerController::OnSendReturnMessage( 324 void WebIntentPickerController::OnSendReturnMessage(
231 webkit_glue::WebIntentReplyType reply_type) { 325 webkit_glue::WebIntentReplyType reply_type) {
232 ClosePicker(); 326 ClosePicker();
233 327
234 if (service_tab_ && 328 if (service_tab_ &&
235 reply_type != webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED) { 329 reply_type != webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED) {
236 int index = TabStripModel::kNoTab; 330 int index = TabStripModel::kNoTab;
237 Browser* browser = Browser::GetBrowserForController( 331 Browser* browser = Browser::GetBrowserForController(
238 &service_tab_->GetController(), &index); 332 &service_tab_->GetController(), &index);
239 if (browser) { 333 if (browser) {
240 browser->tabstrip_model()->CloseTabContentsAt( 334 browser->tabstrip_model()->CloseTabContentsAt(
241 index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); 335 index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
242 336
243 // Activate source tab. 337 // Activate source tab.
244 Browser* source_browser = 338 Browser* source_browser =
245 BrowserList::FindBrowserWithWebContents(wrapper_->web_contents()); 339 BrowserList::FindBrowserWithWebContents(wrapper_->web_contents());
246 if (source_browser) { 340 if (source_browser) {
247 int source_index = 341 int source_index =
248 source_browser->tabstrip_model()->GetIndexOfTabContents(wrapper_); 342 source_browser->tabstrip_model()->GetIndexOfTabContents(wrapper_);
249 source_browser->ActivateTabAt(source_index, false); 343 source_browser->ActivateTabAt(source_index, false);
250 } 344 }
251 } 345 }
252 service_tab_ = NULL; 346 service_tab_ = NULL;
253 } 347 }
254 348
255 intents_dispatcher_ = NULL; 349 intents_dispatcher_ = NULL;
256 } 350 }
257 351
258 void WebIntentPickerController::OnIntentsQueryDone( 352 void WebIntentPickerController::OnWebIntentServicesAvailable(
259 WebIntentsRegistry::QueryID,
260 const std::vector<webkit_glue::WebIntentServiceData>& services) { 353 const std::vector<webkit_glue::WebIntentServiceData>& services) {
261 FaviconService* favicon_service = GetFaviconService(wrapper_); 354 FaviconService* favicon_service = GetFaviconService(wrapper_);
262 for (size_t i = 0; i < services.size(); ++i) { 355 for (size_t i = 0; i < services.size(); ++i) {
263 picker_model_->AddInstalledService( 356 picker_model_->AddInstalledService(
264 services[i].title, 357 services[i].title,
265 services[i].service_url, 358 services[i].service_url,
266 ConvertDisposition(services[i].disposition)); 359 ConvertDisposition(services[i].disposition));
267 360
268 pending_async_count_++; 361 pending_async_count_++;
269 FaviconService::Handle handle = favicon_service->GetFaviconForURL( 362 FaviconService::Handle handle = favicon_service->GetFaviconForURL(
270 services[i].service_url, 363 services[i].service_url,
271 history::FAVICON, 364 history::FAVICON,
272 &favicon_consumer_, 365 &favicon_consumer_,
273 base::Bind( 366 base::Bind(
274 &WebIntentPickerController::OnFaviconDataAvailable, 367 &WebIntentPickerController::OnFaviconDataAvailable,
275 weak_ptr_factory_.GetWeakPtr())); 368 weak_ptr_factory_.GetWeakPtr()));
276 favicon_consumer_.SetClientData(favicon_service, handle, i); 369 favicon_consumer_.SetClientData(favicon_service, handle, i);
277 } 370 }
278 371
279 AsyncOperationFinished(); 372 AsyncOperationFinished();
280 } 373 }
281 374
282 void WebIntentPickerController::OnIntentsDefaultsQueryDone(
283 WebIntentsRegistry::QueryID,
284 const DefaultWebIntentService& default_service) {
285 }
286
287 void WebIntentPickerController::OnFaviconDataAvailable( 375 void WebIntentPickerController::OnFaviconDataAvailable(
288 FaviconService::Handle handle, history::FaviconData favicon_data) { 376 FaviconService::Handle handle, history::FaviconData favicon_data) {
289 size_t index = favicon_consumer_.GetClientDataForCurrentRequest(); 377 size_t index = favicon_consumer_.GetClientDataForCurrentRequest();
290 if (favicon_data.is_valid()) { 378 if (favicon_data.is_valid()) {
291 SkBitmap icon_bitmap; 379 SkBitmap icon_bitmap;
292 380
293 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), 381 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(),
294 favicon_data.image_data->size(), 382 favicon_data.image_data->size(),
295 &icon_bitmap)) { 383 &icon_bitmap)) {
296 gfx::Image icon_image(new SkBitmap(icon_bitmap)); 384 gfx::Image icon_image(new SkBitmap(icon_bitmap));
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 const gfx::Image& icon_image) { 497 const gfx::Image& icon_image) {
410 picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image); 498 picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image);
411 AsyncOperationFinished(); 499 AsyncOperationFinished();
412 } 500 }
413 501
414 void WebIntentPickerController::OnExtensionIconUnavailable( 502 void WebIntentPickerController::OnExtensionIconUnavailable(
415 const string16& extension_id) { 503 const string16& extension_id) {
416 AsyncOperationFinished(); 504 AsyncOperationFinished();
417 } 505 }
418 506
507 void WebIntentPickerController::OnExtensionInstallServiceAvailable(
508 const std::vector<webkit_glue::WebIntentServiceData>& services) {
509 DCHECK(services.size() > 0);
510
511 // TODO(binji): We're going to need to disambiguate if there are multiple
512 // services. For now, just choose the first.
513 const webkit_glue::WebIntentServiceData& service_data = services[0];
514 OnServiceChosen(
515 service_data.service_url,
516 ConvertDisposition(service_data.disposition));
517 AsyncOperationFinished();
518 }
519
419 void WebIntentPickerController::AsyncOperationFinished() { 520 void WebIntentPickerController::AsyncOperationFinished() {
420 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 521 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
421 if (--pending_async_count_ == 0) { 522 if (--pending_async_count_ == 0) {
422 picker_->OnPendingAsyncCompleted(); 523 picker_->OnPendingAsyncCompleted();
423 } 524 }
424 } 525 }
425 526
426 void WebIntentPickerController::ClosePicker() { 527 void WebIntentPickerController::ClosePicker() {
427 if (picker_) { 528 if (picker_) {
428 picker_->Close(); 529 picker_->Close();
429 } 530 }
430 } 531 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698