| 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
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d348e4750e11753a248910e9c3bc1d41572a7532
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/intents/web_intent_picker_controller.cc
|
| @@ -0,0 +1,264 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/ui/intents/web_intent_picker_controller.h"
|
| +
|
| +#include <vector>
|
| +
|
| +#include "chrome/browser/favicon/favicon_service.h"
|
| +#include "chrome/browser/intents/web_intent_data.h"
|
| +#include "chrome/browser/intents/web_intents_registry.h"
|
| +#include "chrome/browser/intents/web_intents_registry_factory.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/ui/intents/web_intent_picker.h"
|
| +#include "chrome/browser/ui/intents/web_intent_picker_factory.h"
|
| +#include "chrome/browser/webdata/web_data_service.h"
|
| +#include "content/browser/tab_contents/tab_contents.h"
|
| +#include "content/common/notification_source.h"
|
| +#include "ui/gfx/codec/png_codec.h"
|
| +
|
| +namespace {
|
| +
|
| +// Gets the favicon service for the profile in |tab_contents|.
|
| +FaviconService* GetFaviconService(TabContents* tab_contents) {
|
| + Profile* profile = Profile::FromBrowserContext(
|
| + tab_contents->browser_context());
|
| + return profile->GetFaviconService(Profile::EXPLICIT_ACCESS);
|
| +}
|
| +
|
| +// Gets the web intents registry for the profile in |tab_contents|.
|
| +WebIntentsRegistry* GetWebIntentsRegistry(TabContents* tab_contents) {
|
| + Profile* profile = Profile::FromBrowserContext(
|
| + tab_contents->browser_context());
|
| + return WebIntentsRegistryFactory::GetForProfile(profile);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// A class that asynchronously fetches web intent data from the web intents
|
| +// registry.
|
| +class WebIntentPickerController::WebIntentDataFetcher
|
| + : public WebIntentsRegistry::Consumer {
|
| + public:
|
| + WebIntentDataFetcher(WebIntentPickerController* controller,
|
| + WebIntentsRegistry* web_intents_registry);
|
| + ~WebIntentDataFetcher();
|
| +
|
| + // Asynchronously fetches WebIntentData for the given |action| |type| pair.
|
| + void Fetch(const string16& action, const string16& type);
|
| +
|
| + // Cancels the WebDataService request.
|
| + void Cancel();
|
| +
|
| + private:
|
| + // WebIntentsRegistry::Consumer implementation.
|
| + virtual void OnIntentsQueryDone(
|
| + WebIntentsRegistry::QueryID,
|
| + const std::vector<WebIntentData>& intents) OVERRIDE;
|
| +
|
| + // A weak pointer to the picker controller.
|
| + WebIntentPickerController* controller_;
|
| +
|
| + // A weak pointer to the web intents registry.
|
| + WebIntentsRegistry* web_intents_registry_;
|
| +
|
| + // The ID of the current web intents request. The value will be -1 if
|
| + // there is no request in flight.
|
| + WebIntentsRegistry::QueryID query_id_;
|
| +};
|
| +
|
| +// A class that asynchronously fetches favicons for a vector of URLs.
|
| +class WebIntentPickerController::FaviconFetcher {
|
| + public:
|
| + FaviconFetcher(WebIntentPickerController* controller,
|
| + FaviconService *favicon_service);
|
| + ~FaviconFetcher();
|
| +
|
| + // Asynchronously fetches favicons for the each URL in |urls|.
|
| + void Fetch(const std::vector<GURL>& urls);
|
| +
|
| + // Cancels all favicon requests.
|
| + void Cancel();
|
| +
|
| + private:
|
| + // Callback called when a favicon is received.
|
| + void OnFaviconDataAvailable(FaviconService::Handle handle,
|
| + history::FaviconData favicon_data);
|
| +
|
| + // A weak pointer to the picker controller.
|
| + WebIntentPickerController* controller_;
|
| +
|
| + // A weak pointer to the favicon service.
|
| + FaviconService* favicon_service_;
|
| +
|
| + // The Consumer to handle asynchronous favicon requests.
|
| + CancelableRequestConsumerTSimple<size_t> load_consumer_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FaviconFetcher);
|
| +};
|
| +
|
| +WebIntentPickerController::WebIntentPickerController(
|
| + TabContents* tab_contents,
|
| + WebIntentPickerFactory* factory)
|
| + : tab_contents_(tab_contents),
|
| + picker_factory_(factory),
|
| + web_intent_data_fetcher_(
|
| + new WebIntentDataFetcher(this,
|
| + GetWebIntentsRegistry(tab_contents))),
|
| + favicon_fetcher_(
|
| + new FaviconFetcher(this, GetFaviconService(tab_contents))),
|
| + picker_(NULL),
|
| + pending_async_count_(0) {
|
| + NavigationController* controller = &tab_contents->controller();
|
| + registrar_.Add(this, content::NOTIFICATION_LOAD_START,
|
| + Source<NavigationController>(controller));
|
| + registrar_.Add(this, content::NOTIFICATION_TAB_CLOSING,
|
| + Source<NavigationController>(controller));
|
| +}
|
| +
|
| +WebIntentPickerController::~WebIntentPickerController() {
|
| +}
|
| +
|
| +void WebIntentPickerController::ShowDialog(const string16& action,
|
| + const string16& type) {
|
| + if (picker_ != NULL)
|
| + return;
|
| +
|
| + picker_ = picker_factory_->Create(tab_contents_, this);
|
| +
|
| + // TODO(binji) Remove this check when there are implementations of the picker
|
| + // for windows and mac.
|
| + if (picker_ == NULL)
|
| + return;
|
| +
|
| + web_intent_data_fetcher_->Fetch(action, type);
|
| +}
|
| +
|
| +void WebIntentPickerController::Observe(int type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) {
|
| + DCHECK(type == content::NOTIFICATION_LOAD_START ||
|
| + type == content::NOTIFICATION_TAB_CLOSING);
|
| + ClosePicker();
|
| +}
|
| +
|
| +void WebIntentPickerController::OnServiceChosen(size_t index) {
|
| + DCHECK(index < urls_.size());
|
| +
|
| + // TODO(binji) Send the chosen service back to the renderer.
|
| + LOG(INFO) << "Chose index: " << index << " url: " << urls_[index];
|
| + ClosePicker();
|
| +}
|
| +
|
| +void WebIntentPickerController::OnCancelled() {
|
| + // TODO(binji) Tell the renderer that the intent was cancelled.
|
| + ClosePicker();
|
| +}
|
| +
|
| +void WebIntentPickerController::OnWebIntentDataAvailable(
|
| + const std::vector<WebIntentData>& intent_data) {
|
| + urls_.clear();
|
| + for (size_t i = 0; i < intent_data.size(); ++i) {
|
| + urls_.push_back(intent_data[i].service_url);
|
| + }
|
| +
|
| + // Tell the picker to initialize N urls to the default favicon
|
| + picker_->SetServiceURLs(urls_);
|
| + favicon_fetcher_->Fetch(urls_);
|
| + pending_async_count_--;
|
| +}
|
| +
|
| +void WebIntentPickerController::OnFaviconDataAvailable(
|
| + size_t index,
|
| + const SkBitmap& icon_bitmap) {
|
| + picker_->SetServiceIcon(index, icon_bitmap);
|
| + pending_async_count_--;
|
| +}
|
| +
|
| +void WebIntentPickerController::OnFaviconDataUnavailable(size_t index) {
|
| + picker_->SetDefaultServiceIcon(index);
|
| + pending_async_count_--;
|
| +}
|
| +
|
| +void WebIntentPickerController::ClosePicker() {
|
| + if (picker_) {
|
| + picker_factory_->ClosePicker(picker_);
|
| + picker_ = NULL;
|
| + }
|
| +}
|
| +
|
| +WebIntentPickerController::WebIntentDataFetcher::WebIntentDataFetcher(
|
| + WebIntentPickerController* controller,
|
| + WebIntentsRegistry* web_intents_registry)
|
| + : controller_(controller),
|
| + web_intents_registry_(web_intents_registry),
|
| + query_id_(-1) {
|
| +}
|
| +
|
| +WebIntentPickerController::WebIntentDataFetcher::~WebIntentDataFetcher() {
|
| +}
|
| +
|
| +void WebIntentPickerController::WebIntentDataFetcher::Fetch(
|
| + const string16& action,
|
| + const string16& type) {
|
| + DCHECK(query_id_ == -1) << "Fetch already in process.";
|
| + controller_->pending_async_count_++;
|
| + query_id_ = web_intents_registry_->GetIntentProviders(action, this);
|
| +}
|
| +
|
| +void WebIntentPickerController::WebIntentDataFetcher::OnIntentsQueryDone(
|
| + WebIntentsRegistry::QueryID,
|
| + const std::vector<WebIntentData>& intents) {
|
| + controller_->OnWebIntentDataAvailable(intents);
|
| + query_id_ = -1;
|
| +}
|
| +
|
| +WebIntentPickerController::FaviconFetcher::FaviconFetcher(
|
| + WebIntentPickerController* controller,
|
| + FaviconService* favicon_service)
|
| + : controller_(controller),
|
| + favicon_service_(favicon_service) {
|
| +}
|
| +
|
| +WebIntentPickerController::FaviconFetcher::~FaviconFetcher() {
|
| +}
|
| +
|
| +void WebIntentPickerController::FaviconFetcher::Fetch(
|
| + const std::vector<GURL>& urls) {
|
| + if (!favicon_service_)
|
| + return;
|
| +
|
| + for (size_t index = 0; index < urls.size(); ++index) {
|
| + controller_->pending_async_count_++;
|
| + FaviconService::Handle handle = favicon_service_->GetFaviconForURL(
|
| + urls[index],
|
| + history::FAVICON,
|
| + &load_consumer_,
|
| + NewCallback(this, &WebIntentPickerController::FaviconFetcher::
|
| + OnFaviconDataAvailable));
|
| + load_consumer_.SetClientData(favicon_service_, handle, index);
|
| + }
|
| +}
|
| +
|
| +void WebIntentPickerController::FaviconFetcher::Cancel() {
|
| + load_consumer_.CancelAllRequests();
|
| +}
|
| +
|
| +void WebIntentPickerController::FaviconFetcher::OnFaviconDataAvailable(
|
| + FaviconService::Handle handle,
|
| + history::FaviconData favicon_data) {
|
| + size_t index = load_consumer_.GetClientDataForCurrentRequest();
|
| + if (favicon_data.is_valid()) {
|
| + SkBitmap icon_bitmap;
|
| +
|
| + if (gfx::PNGCodec::Decode(favicon_data.image_data->front(),
|
| + favicon_data.image_data->size(),
|
| + &icon_bitmap)) {
|
| + controller_->OnFaviconDataAvailable(index, icon_bitmap);
|
| + return;
|
| + }
|
| + }
|
| +
|
| + controller_->OnFaviconDataUnavailable(index);
|
| +}
|
|
|