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