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

Unified Diff: chrome/browser/ui/intents/web_intent_picker_controller.cc

Issue 10204010: Handling default service in the web intents picker controller. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/intents/web_intent_picker_controller.cc
diff --git a/chrome/browser/ui/intents/web_intent_picker_controller.cc b/chrome/browser/ui/intents/web_intent_picker_controller.cc
index 868609ff94fe3b8e10ec69bfd2199d79f18d8192..32221f98f811c909bae80ce3014ffd1d9fde8c6e 100644
--- a/chrome/browser/ui/intents/web_intent_picker_controller.cc
+++ b/chrome/browser/ui/intents/web_intent_picker_controller.cc
@@ -26,6 +26,7 @@
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_source.h"
@@ -164,32 +165,66 @@ void WebIntentPickerController::ShowDialog(Browser* browser,
const string16& action,
const string16& type) {
// Only show a picker once.
- if (picker_shown_)
- return;
-
+ // ??? Is this good enough? There's a hole if we don't create the picker
+ // in this method, but only after disk retrieval.
// TODO(binji): Figure out what to do when intents are invoked from incognito
// mode.
- if (wrapper_->profile()->IsOffTheRecord())
+ if (picker_shown_ || wrapper_->profile()->IsOffTheRecord()) {
+ if (intents_dispatcher_) {
+ intents_dispatcher_->SendReplyMessage(
+ webkit_glue::WEB_INTENT_REPLY_FAILURE, ASCIIToUTF16(""));
+ }
return;
+ }
+ browser_ = browser;
+ action_ = action;
picker_model_->Clear();
picker_model_->set_action(action);
picker_model_->set_mimetype(type);
- // If picker is non-NULL, it was set by a test.
- if (picker_ == NULL) {
- picker_ = WebIntentPicker::Create(browser, wrapper_, this,
- picker_model_.get());
+ // If the intent is explicit, skip showing the picker.
+ if (intents_dispatcher_) {
+ const GURL& service = intents_dispatcher_->GetIntent().service;
+ // TODO(gbillock): When we can parse pages for the intent tag,
+ // take out this requirement that explicit intents dispatch to
+ // extension urls.
+ if (!service.is_valid() || !service.SchemeIs(chrome::kExtensionScheme)) {
+ intents_dispatcher_->SendReplyMessage(
+ webkit_glue::WEB_INTENT_REPLY_FAILURE, ASCIIToUTF16(
+ "Only extension urls are supported for explicit invocation"));
+ return;
+ }
+
+ // We get services from the registry because that must retrieve the
+ // registered extension page for this action/type if it is permitted to be
+ // dispatched.
+ pending_async_count_++;
+ GetWebIntentsRegistry(wrapper_)->GetIntentServices(
+ action, type, base::Bind(
+ &WebIntentPickerController::WebIntentServicesForExplicitIntent,
+ weak_ptr_factory_.GetWeakPtr()));
+ return;
}
- picker_->SetActionString(GetIntentActionString(UTF16ToUTF8(action)));
+ pending_async_count_ += 2;
groby-ooo-7-16 2012/04/24 21:36:51 Why exactly do we keep a pending count? (Nobody im
Greg Billock 2012/04/25 16:04:32 I thought it was used to guide the operation of th
+ pending_registry_calls_count_ += 1;
groby-ooo-7-16 2012/04/24 21:36:51 Why add 1 here? We already do that when we call th
Greg Billock 2012/04/25 16:04:32 There's now two registry callbacks we need to wait
- picker_shown_ = true;
- pending_async_count_+= 2;
GetWebIntentsRegistry(wrapper_)->GetIntentServices(
action, type,
base::Bind(&WebIntentPickerController::OnWebIntentServicesAvailable,
weak_ptr_factory_.GetWeakPtr()));
+
+ GURL invoking_url = wrapper_->web_contents()->GetURL();
+ if (invoking_url.is_valid()) {
+ pending_async_count_++;
+ pending_registry_calls_count_++;
+ GetWebIntentsRegistry(wrapper_)->GetDefaultIntentService(
+ action, type, invoking_url,
+ base::Bind(&WebIntentPickerController::OnWebIntentDefaultsAvailable,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
GetCWSIntentsRegistry(wrapper_)->GetIntentServices(
action, type,
base::Bind(&WebIntentPickerController::OnCWSIntentServicesAvailable,
@@ -216,12 +251,8 @@ void WebIntentPickerController::OnServiceChosen(const GURL& url,
break;
case WebIntentPickerModel::DISPOSITION_WINDOW: {
- // TODO(gbillock): This really only handles the 'window' disposition in a
- // quite prototype way. We need to flesh out what happens to the picker
- // during the lifetime of the service url context, and that may mean we
- // need to pass more information into the injector to find the picker
- // again and close it.
int index = TabStripModel::kNoTab;
+ // TODO(gbillock): use browser_?
groby-ooo-7-16 2012/04/24 21:36:51 I believe there has been a CL (or there is one in
Greg Billock 2012/04/25 16:04:32 got rid of this. I'll add a todo to scrap the Show
Browser* browser = Browser::GetBrowserForController(
&wrapper_->web_contents()->GetController(), &index);
TabContentsWrapper* contents = Browser::TabContentsFactory(
@@ -277,6 +308,7 @@ void WebIntentPickerController::OnExtensionInstallRequested(
void WebIntentPickerController::OnExtensionLinkClicked(const std::string& id) {
// Navigate from source tab.
+ // TODO(gbillock): use browser_?
groby-ooo-7-16 2012/04/24 21:36:51 See above
Greg Billock 2012/04/25 16:04:32 Done.
Browser* browser =
BrowserList::FindBrowserWithWebContents(wrapper_->web_contents());
GURL extension_url(extension_urls::GetWebstoreItemDetailURLPrefix() + id);
@@ -345,6 +377,7 @@ void WebIntentPickerController::OnSendReturnMessage(
if (service_tab_ &&
reply_type != webkit_glue::WEB_INTENT_SERVICE_CONTENTS_CLOSED) {
int index = TabStripModel::kNoTab;
+ // TODO(gbillock): use browser_?
groby-ooo-7-16 2012/04/24 21:36:51 See above
Greg Billock 2012/04/25 16:04:32 Done.
Browser* browser = Browser::GetBrowserForController(
&service_tab_->GetController(), &index);
if (browser) {
@@ -386,9 +419,72 @@ void WebIntentPickerController::OnWebIntentServicesAvailable(
favicon_consumer_.SetClientData(favicon_service, handle, i);
}
+ RegistryCallsCompleted();
groby-ooo-7-16 2012/04/24 21:36:51 Why do we flag registry calls completed here, not
Greg Billock 2012/04/25 16:04:32 Bad name. This is the method we want to happen whe
+ AsyncOperationFinished();
+}
+
+void WebIntentPickerController::WebIntentServicesForExplicitIntent(
+ const std::vector<webkit_glue::WebIntentServiceData>& services) {
+ DCHECK(intents_dispatcher_);
+ DCHECK(intents_dispatcher_->GetIntent().service.is_valid());
+ for (size_t i = 0; i < services.size(); ++i) {
+ if (services[i].service_url != intents_dispatcher_->GetIntent().service)
+ continue;
+
+ if (services[i].disposition ==
+ webkit_glue::WebIntentServiceData::DISPOSITION_INLINE)
+ CreatePicker();
groby-ooo-7-16 2012/04/24 21:36:51 This is more of a TBD, but I really think we need
Greg Billock 2012/04/25 16:04:32 Makes sense.
+ OnServiceChosen(services[i].service_url,
+ ConvertDisposition(services[i].disposition));
+ return;
+ }
+
+ // We did not find an acceptable extension. The intent cannot
+ // be dispatched.
+ intents_dispatcher_->SendReplyMessage(
+ webkit_glue::WEB_INTENT_REPLY_FAILURE, ASCIIToUTF16(
+ "Explicit extension URL is not available."));
+
+ // Finished.
+ AsyncOperationFinished();
+}
+
+void WebIntentPickerController::OnWebIntentDefaultsAvailable(
+ const DefaultWebIntentService& default_service) {
+ if (!default_service.service_url.empty()) {
+ DCHECK(default_service.suppression == 0);
+ default_service_url_ = default_service.service_url;
+ }
+
+ RegistryCallsCompleted();
AsyncOperationFinished();
}
+void WebIntentPickerController::RegistryCallsCompleted() {
+ if (--pending_registry_calls_count_ != 0) return;
+
+ if (!default_service_url_.empty()) {
+ // If there's a default service, dispatch to it immediately
+ // without showing the picker.
+ const WebIntentPickerModel::InstalledService* default_service =
+ picker_model_->GetInstalledServiceWithURL(GURL(default_service_url_));
+
+ if (default_service != NULL) {
+ if (default_service->disposition ==
+ WebIntentPickerModel::DISPOSITION_INLINE)
+ CreatePicker();
+ OnServiceChosen(default_service->url, default_service->disposition);
+ return;
+ }
+ }
+
+ CreatePicker();
+ picker_->SetActionString(GetIntentActionString(UTF16ToUTF8(action_)));
+
+ // TODO(gbillock): handle the case of having only one service -- set
+ // the make-default checkbox to "true" upon display.
+}
+
void WebIntentPickerController::OnFaviconDataAvailable(
FaviconService::Handle handle, history::FaviconData favicon_data) {
size_t index = favicon_consumer_.GetClientDataForCurrentRequest();
@@ -549,6 +645,18 @@ void WebIntentPickerController::AsyncOperationFinished() {
}
}
+void WebIntentPickerController::CreatePicker() {
+ // If picker is non-NULL, it was set by a test.
+ // Use browser_?
+ Browser* browser =
+ BrowserList::FindBrowserWithWebContents(wrapper_->web_contents());
+ if (picker_ == NULL) {
+ picker_ = WebIntentPicker::Create(browser, wrapper_, this,
+ picker_model_.get());
+ }
+ picker_shown_ = true;
+}
+
void WebIntentPickerController::ClosePicker() {
if (picker_)
picker_->Close();

Powered by Google App Engine
This is Rietveld 408576698