OLD | NEW |
---|---|
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 Loading... | |
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 // WebIntentsRegistryTrampoline ----------------------------------------------- | |
James Hawkins
2012/03/15 01:05:20
Kill this line, preferably via fire.
binji
2012/03/15 17:53:14
Done.
| |
72 | |
73 class WebIntentsRegistryTrampoline : public WebIntentsRegistry::Consumer { | |
James Hawkins
2012/03/15 01:05:20
Document the class.
binji
2012/03/15 17:53:14
Done.
| |
74 public: | |
75 typedef std::vector<webkit_glue::WebIntentServiceData> IntentServices; | |
76 typedef base::Callback<void(const IntentServices&)> Callback; | |
James Hawkins
2012/03/15 01:05:20
Pick a less generic name than Callback.
binji
2012/03/15 17:53:14
Done.
| |
77 | |
78 explicit WebIntentsRegistryTrampoline(const Callback& callback); | |
James Hawkins
2012/03/15 01:05:20
|callback| must not be null?
binji
2012/03/15 17:53:14
Done.
| |
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 Callback callback_; | |
James Hawkins
2012/03/15 01:05:20
Document member variable.
binji
2012/03/15 17:53:14
Done.
| |
91 }; | |
92 | |
93 WebIntentsRegistryTrampoline::WebIntentsRegistryTrampoline( | |
94 const Callback& callback) | |
95 : callback_(callback) { | |
96 } | |
97 | |
98 WebIntentsRegistryTrampoline::~WebIntentsRegistryTrampoline() { | |
99 } | |
100 | |
101 void WebIntentsRegistryTrampoline::OnIntentsQueryDone( | |
102 WebIntentsRegistry::QueryID, | |
103 const std::vector<webkit_glue::WebIntentServiceData>& services) { | |
104 callback_.Run(services); | |
105 delete this; | |
106 } | |
107 | |
108 // URLFetcherTrampoline ------------------------------------------------------- | |
109 | |
69 class URLFetcherTrampoline : public content::URLFetcherDelegate { | 110 class URLFetcherTrampoline : public content::URLFetcherDelegate { |
70 public: | 111 public: |
71 typedef base::Callback<void(const content::URLFetcher* source)> Callback; | 112 typedef base::Callback<void(const content::URLFetcher* source)> Callback; |
72 | 113 |
73 explicit URLFetcherTrampoline(const Callback& callback) | 114 explicit URLFetcherTrampoline(const Callback& callback); |
74 : callback_(callback) {} | 115 ~URLFetcherTrampoline(); |
75 ~URLFetcherTrampoline() {} | |
76 | 116 |
77 // content::URLFetcherDelegate implementation. | 117 // content::URLFetcherDelegate implementation. |
78 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE { | 118 virtual void OnURLFetchComplete(const content::URLFetcher* source) OVERRIDE; |
79 callback_.Run(source); | |
80 delete source; | |
81 delete this; | |
82 } | |
83 | 119 |
84 private: | 120 private: |
85 Callback callback_; | 121 Callback callback_; |
86 }; | 122 }; |
87 | 123 |
124 URLFetcherTrampoline::URLFetcherTrampoline(const Callback& callback) | |
125 : callback_(callback) { | |
126 } | |
127 | |
128 URLFetcherTrampoline::~URLFetcherTrampoline() { | |
129 } | |
130 | |
131 void URLFetcherTrampoline::OnURLFetchComplete( | |
132 const content::URLFetcher* source) { | |
133 callback_.Run(source); | |
134 delete source; | |
135 delete this; | |
136 } | |
137 | |
88 } // namespace | 138 } // namespace |
89 | 139 |
90 WebIntentPickerController::WebIntentPickerController( | 140 WebIntentPickerController::WebIntentPickerController( |
91 TabContentsWrapper* wrapper) | 141 TabContentsWrapper* wrapper) |
92 : wrapper_(wrapper), | 142 : wrapper_(wrapper), |
93 picker_(NULL), | 143 picker_(NULL), |
94 picker_model_(new WebIntentPickerModel()), | 144 picker_model_(new WebIntentPickerModel()), |
95 pending_async_count_(0), | 145 pending_async_count_(0), |
96 picker_shown_(false), | 146 picker_shown_(false), |
97 intents_dispatcher_(NULL), | 147 intents_dispatcher_(NULL), |
(...skipping 19 matching lines...) Expand all Loading... | |
117 } | 167 } |
118 | 168 |
119 void WebIntentPickerController::ShowDialog(Browser* browser, | 169 void WebIntentPickerController::ShowDialog(Browser* browser, |
120 const string16& action, | 170 const string16& action, |
121 const string16& type) { | 171 const string16& type) { |
122 // Only show a picker once. | 172 // Only show a picker once. |
123 if (picker_shown_) | 173 if (picker_shown_) |
124 return; | 174 return; |
125 | 175 |
126 picker_model_->Clear(); | 176 picker_model_->Clear(); |
177 picker_model_->set_action(action); | |
178 picker_model_->set_mimetype(type); | |
127 | 179 |
128 // If picker is non-NULL, it was set by a test. | 180 // If picker is non-NULL, it was set by a test. |
129 if (picker_ == NULL) { | 181 if (picker_ == NULL) { |
130 picker_ = WebIntentPicker::Create(browser, wrapper_, this, | 182 picker_ = WebIntentPicker::Create(browser, wrapper_, this, |
131 picker_model_.get()); | 183 picker_model_.get()); |
132 } | 184 } |
133 | 185 |
134 picker_shown_ = true; | 186 picker_shown_ = true; |
135 pending_async_count_+= 2; | 187 pending_async_count_+= 2; |
136 GetWebIntentsRegistry(wrapper_)->GetIntentServices(action, type, this); | 188 GetWebIntentsRegistry(wrapper_)->GetIntentServices( |
137 GetCWSIntentsRegistry(wrapper_)->GetIntentServices(action, type, | 189 action, type, |
190 new WebIntentsRegistryTrampoline( | |
James Hawkins
2012/03/15 01:05:20
Document ownership.
binji
2012/03/15 17:53:14
Done.
| |
191 base::Bind(&WebIntentPickerController::OnWebIntentServicesAvailable, | |
192 weak_ptr_factory_.GetWeakPtr()))); | |
193 GetCWSIntentsRegistry(wrapper_)->GetIntentServices( | |
194 action, type, | |
138 base::Bind(&WebIntentPickerController::OnCWSIntentServicesAvailable, | 195 base::Bind(&WebIntentPickerController::OnCWSIntentServicesAvailable, |
139 weak_ptr_factory_.GetWeakPtr())); | 196 weak_ptr_factory_.GetWeakPtr())); |
140 } | 197 } |
141 | 198 |
142 void WebIntentPickerController::Observe( | 199 void WebIntentPickerController::Observe( |
143 int type, | 200 int type, |
144 const content::NotificationSource& source, | 201 const content::NotificationSource& source, |
145 const content::NotificationDetails& details) { | 202 const content::NotificationDetails& details) { |
146 DCHECK(type == content::NOTIFICATION_LOAD_START || | 203 DCHECK(type == content::NOTIFICATION_LOAD_START || |
147 type == content::NOTIFICATION_TAB_CLOSING); | 204 type == content::NOTIFICATION_TAB_CLOSING); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
200 break; | 257 break; |
201 } | 258 } |
202 } | 259 } |
203 | 260 |
204 void WebIntentPickerController::OnInlineDispositionWebContentsCreated( | 261 void WebIntentPickerController::OnInlineDispositionWebContentsCreated( |
205 content::WebContents* web_contents) { | 262 content::WebContents* web_contents) { |
206 if (web_contents) | 263 if (web_contents) |
207 intents_dispatcher_->DispatchIntent(web_contents); | 264 intents_dispatcher_->DispatchIntent(web_contents); |
208 } | 265 } |
209 | 266 |
267 void WebIntentPickerController::OnExtensionInstallRequested( | |
268 const std::string& id) { | |
269 webstore_installer_ = new WebstoreInstaller( | |
270 wrapper_->profile(), | |
James Hawkins
2012/03/15 01:05:20
Save rows by collapsing these parameters.
binji
2012/03/15 17:53:14
Done.
| |
271 this, | |
272 &wrapper_->web_contents()->GetController(), | |
273 id, | |
274 WebstoreInstaller::FLAG_INLINE_INSTALL); | |
275 | |
276 pending_async_count_++; | |
277 webstore_installer_->Start(); | |
278 } | |
279 | |
210 void WebIntentPickerController::OnCancelled() { | 280 void WebIntentPickerController::OnCancelled() { |
211 if (!intents_dispatcher_) | 281 if (!intents_dispatcher_) |
212 return; | 282 return; |
213 | 283 |
214 if (service_tab_) { | 284 if (service_tab_) { |
215 intents_dispatcher_->SendReplyMessage( | 285 intents_dispatcher_->SendReplyMessage( |
216 webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED, string16()); | 286 webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED, string16()); |
217 } else { | 287 } else { |
218 intents_dispatcher_->SendReplyMessage( | 288 intents_dispatcher_->SendReplyMessage( |
219 webkit_glue::WEB_INTENT_PICKER_CANCELLED, string16()); | 289 webkit_glue::WEB_INTENT_PICKER_CANCELLED, string16()); |
220 } | 290 } |
221 | 291 |
222 ClosePicker(); | 292 ClosePicker(); |
223 } | 293 } |
224 | 294 |
225 void WebIntentPickerController::OnClosing() { | 295 void WebIntentPickerController::OnClosing() { |
226 picker_shown_ = false; | 296 picker_shown_ = false; |
227 picker_ = NULL; | 297 picker_ = NULL; |
228 } | 298 } |
229 | 299 |
300 void WebIntentPickerController::OnExtensionInstallSuccess( | |
301 const std::string& id) { | |
302 picker_->OnExtensionInstallSuccess(id); | |
303 pending_async_count_++; | |
304 GetWebIntentsRegistry(wrapper_)->GetIntentServicesWithExtensionId( | |
305 picker_model_->action(), | |
306 picker_model_->mimetype(), | |
307 id, | |
308 new WebIntentsRegistryTrampoline( | |
309 base::Bind( | |
310 &WebIntentPickerController::OnExtensionInstallServiceAvailable, | |
311 weak_ptr_factory_.GetWeakPtr()))); | |
312 AsyncOperationFinished(); | |
313 } | |
314 | |
315 void WebIntentPickerController::OnExtensionInstallFailure( | |
316 const std::string& id, | |
317 const std::string& error) { | |
318 picker_->OnExtensionInstallFailure(id); | |
319 AsyncOperationFinished(); | |
320 } | |
321 | |
230 void WebIntentPickerController::OnSendReturnMessage( | 322 void WebIntentPickerController::OnSendReturnMessage( |
231 webkit_glue::WebIntentReplyType reply_type) { | 323 webkit_glue::WebIntentReplyType reply_type) { |
232 ClosePicker(); | 324 ClosePicker(); |
233 | 325 |
234 if (service_tab_ && | 326 if (service_tab_ && |
235 reply_type != webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED) { | 327 reply_type != webkit_glue::WEB_INTENT_SERVICE_TAB_CLOSED) { |
236 int index = TabStripModel::kNoTab; | 328 int index = TabStripModel::kNoTab; |
237 Browser* browser = Browser::GetBrowserForController( | 329 Browser* browser = Browser::GetBrowserForController( |
238 &service_tab_->GetController(), &index); | 330 &service_tab_->GetController(), &index); |
239 if (browser) { | 331 if (browser) { |
240 browser->tabstrip_model()->CloseTabContentsAt( | 332 browser->tabstrip_model()->CloseTabContentsAt( |
241 index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); | 333 index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); |
242 | 334 |
243 // Activate source tab. | 335 // Activate source tab. |
244 Browser* source_browser = | 336 Browser* source_browser = |
245 BrowserList::FindBrowserWithWebContents(wrapper_->web_contents()); | 337 BrowserList::FindBrowserWithWebContents(wrapper_->web_contents()); |
246 if (source_browser) { | 338 if (source_browser) { |
247 int source_index = | 339 int source_index = |
248 source_browser->tabstrip_model()->GetIndexOfTabContents(wrapper_); | 340 source_browser->tabstrip_model()->GetIndexOfTabContents(wrapper_); |
249 source_browser->ActivateTabAt(source_index, false); | 341 source_browser->ActivateTabAt(source_index, false); |
250 } | 342 } |
251 } | 343 } |
252 service_tab_ = NULL; | 344 service_tab_ = NULL; |
253 } | 345 } |
254 | 346 |
255 intents_dispatcher_ = NULL; | 347 intents_dispatcher_ = NULL; |
256 } | 348 } |
257 | 349 |
258 void WebIntentPickerController::OnIntentsQueryDone( | 350 void WebIntentPickerController::OnWebIntentServicesAvailable( |
259 WebIntentsRegistry::QueryID, | |
260 const std::vector<webkit_glue::WebIntentServiceData>& services) { | 351 const std::vector<webkit_glue::WebIntentServiceData>& services) { |
261 FaviconService* favicon_service = GetFaviconService(wrapper_); | 352 FaviconService* favicon_service = GetFaviconService(wrapper_); |
262 for (size_t i = 0; i < services.size(); ++i) { | 353 for (size_t i = 0; i < services.size(); ++i) { |
263 picker_model_->AddInstalledService( | 354 picker_model_->AddInstalledService( |
264 services[i].title, | 355 services[i].title, |
265 services[i].service_url, | 356 services[i].service_url, |
266 ConvertDisposition(services[i].disposition)); | 357 ConvertDisposition(services[i].disposition)); |
267 | 358 |
268 pending_async_count_++; | 359 pending_async_count_++; |
269 FaviconService::Handle handle = favicon_service->GetFaviconForURL( | 360 FaviconService::Handle handle = favicon_service->GetFaviconForURL( |
270 services[i].service_url, | 361 services[i].service_url, |
271 history::FAVICON, | 362 history::FAVICON, |
272 &favicon_consumer_, | 363 &favicon_consumer_, |
273 base::Bind( | 364 base::Bind( |
274 &WebIntentPickerController::OnFaviconDataAvailable, | 365 &WebIntentPickerController::OnFaviconDataAvailable, |
275 weak_ptr_factory_.GetWeakPtr())); | 366 weak_ptr_factory_.GetWeakPtr())); |
276 favicon_consumer_.SetClientData(favicon_service, handle, i); | 367 favicon_consumer_.SetClientData(favicon_service, handle, i); |
277 } | 368 } |
278 | 369 |
279 AsyncOperationFinished(); | 370 AsyncOperationFinished(); |
280 } | 371 } |
281 | 372 |
282 void WebIntentPickerController::OnIntentsDefaultsQueryDone( | |
283 WebIntentsRegistry::QueryID, | |
284 const DefaultWebIntentService& default_service) { | |
285 } | |
286 | |
287 void WebIntentPickerController::OnFaviconDataAvailable( | 373 void WebIntentPickerController::OnFaviconDataAvailable( |
288 FaviconService::Handle handle, history::FaviconData favicon_data) { | 374 FaviconService::Handle handle, history::FaviconData favicon_data) { |
289 size_t index = favicon_consumer_.GetClientDataForCurrentRequest(); | 375 size_t index = favicon_consumer_.GetClientDataForCurrentRequest(); |
290 if (favicon_data.is_valid()) { | 376 if (favicon_data.is_valid()) { |
291 SkBitmap icon_bitmap; | 377 SkBitmap icon_bitmap; |
292 | 378 |
293 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), | 379 if (gfx::PNGCodec::Decode(favicon_data.image_data->front(), |
294 favicon_data.image_data->size(), | 380 favicon_data.image_data->size(), |
295 &icon_bitmap)) { | 381 &icon_bitmap)) { |
296 gfx::Image icon_image(new SkBitmap(icon_bitmap)); | 382 gfx::Image icon_image(new SkBitmap(icon_bitmap)); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 const gfx::Image& icon_image) { | 495 const gfx::Image& icon_image) { |
410 picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image); | 496 picker_model_->SetSuggestedExtensionIconWithId(extension_id, icon_image); |
411 AsyncOperationFinished(); | 497 AsyncOperationFinished(); |
412 } | 498 } |
413 | 499 |
414 void WebIntentPickerController::OnExtensionIconUnavailable( | 500 void WebIntentPickerController::OnExtensionIconUnavailable( |
415 const string16& extension_id) { | 501 const string16& extension_id) { |
416 AsyncOperationFinished(); | 502 AsyncOperationFinished(); |
417 } | 503 } |
418 | 504 |
505 void WebIntentPickerController::OnExtensionInstallServiceAvailable( | |
506 const std::vector<webkit_glue::WebIntentServiceData>& services) { | |
James Hawkins
2012/03/15 01:05:20
Document in the header that |services| must be a n
binji
2012/03/15 17:53:14
Done.
| |
507 DCHECK(services.size() > 0); | |
508 | |
509 // TODO(binji): We're going to need to disambiguate if there are multiple | |
510 // services. For now, just choose the first. | |
511 const webkit_glue::WebIntentServiceData& service_data = services[0]; | |
512 OnServiceChosen( | |
513 service_data.service_url, | |
514 ConvertDisposition(service_data.disposition)); | |
515 AsyncOperationFinished(); | |
516 } | |
517 | |
419 void WebIntentPickerController::AsyncOperationFinished() { | 518 void WebIntentPickerController::AsyncOperationFinished() { |
420 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 519 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
421 if (--pending_async_count_ == 0) { | 520 if (--pending_async_count_ == 0) { |
422 picker_->OnPendingAsyncCompleted(); | 521 picker_->OnPendingAsyncCompleted(); |
423 } | 522 } |
424 } | 523 } |
425 | 524 |
426 void WebIntentPickerController::ClosePicker() { | 525 void WebIntentPickerController::ClosePicker() { |
427 if (picker_) { | 526 if (picker_) { |
428 picker_->Close(); | 527 picker_->Close(); |
429 } | 528 } |
430 } | 529 } |
OLD | NEW |