blob: 36547f03530fdecab193b36eb78bf823c67f65e0 [file] [log] [blame]
// Copyright 2015 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/chromeos/launcher_search_provider/launcher_search_provider_service.h"
#include "base/memory/scoped_vector.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service_factory.h"
#include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h"
#include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/permissions/permissions_data.h"
namespace api_launcher_search_provider =
extensions::api::launcher_search_provider;
using extensions::ExtensionId;
using extensions::ExtensionSet;
namespace chromeos {
namespace launcher_search_provider {
Service::Service(Profile* profile,
extensions::ExtensionRegistry* extension_registry)
: profile_(profile),
extension_registry_(extension_registry),
provider_(nullptr),
query_id_(0),
is_query_running_(false) {
extension_registry_->AddObserver(this);
}
Service::~Service() {
extension_registry_->RemoveObserver(this);
}
// static
Service* Service::Get(content::BrowserContext* context) {
return ServiceFactory::Get(context);
}
void Service::OnQueryStarted(app_list::LauncherSearchProvider* provider,
const std::string& query,
const int max_result) {
DCHECK(!is_query_running_);
is_query_running_ = true;
provider_ = provider;
++query_id_;
extensions::EventRouter* event_router =
extensions::EventRouter::Get(profile_);
CacheListenerExtensionIds();
for (const ExtensionId extension_id : *cached_listener_extension_ids_.get()) {
// Convert query_id_ to string here since queryId is defined as string in
// javascript side API while we use uint32 internally to generate it.
event_router->DispatchEventToExtension(
extension_id,
make_scoped_ptr(new extensions::Event(
extensions::events::LAUNCHER_SEARCH_PROVIDER_ON_QUERY_STARTED,
api_launcher_search_provider::OnQueryStarted::kEventName,
api_launcher_search_provider::OnQueryStarted::Create(
query_id_, query, max_result))));
}
}
void Service::OnQueryEnded() {
DCHECK(is_query_running_);
provider_ = nullptr;
extensions::EventRouter* event_router =
extensions::EventRouter::Get(profile_);
CacheListenerExtensionIds();
for (const ExtensionId extension_id : *cached_listener_extension_ids_.get()) {
event_router->DispatchEventToExtension(
extension_id,
make_scoped_ptr(new extensions::Event(
extensions::events::LAUNCHER_SEARCH_PROVIDER_ON_QUERY_ENDED,
api_launcher_search_provider::OnQueryEnded::kEventName,
api_launcher_search_provider::OnQueryEnded::Create(query_id_))));
}
is_query_running_ = false;
}
void Service::OnOpenResult(const ExtensionId& extension_id,
const std::string& item_id) {
CacheListenerExtensionIds();
CHECK(ContainsValue(*cached_listener_extension_ids_.get(), extension_id));
extensions::EventRouter* event_router =
extensions::EventRouter::Get(profile_);
event_router->DispatchEventToExtension(
extension_id,
make_scoped_ptr(new extensions::Event(
extensions::events::LAUNCHER_SEARCH_PROVIDER_ON_OPEN_RESULT,
api_launcher_search_provider::OnOpenResult::kEventName,
api_launcher_search_provider::OnOpenResult::Create(item_id))));
}
void Service::SetSearchResults(
const extensions::Extension* extension,
scoped_ptr<ErrorReporter> error_reporter,
const int query_id,
const std::vector<linked_ptr<
extensions::api::launcher_search_provider::SearchResult>>& results) {
// If query is not running or query_id is different from current query id,
// discard the results.
if (!is_query_running_ || query_id != query_id_)
return;
// If |extension| is not in the listener extensions list, ignore it.
CacheListenerExtensionIds();
if (!ContainsValue(*cached_listener_extension_ids_.get(), extension->id()))
return;
// Set search results to provider.
DCHECK(provider_);
ScopedVector<app_list::LauncherSearchResult> search_results;
for (const auto& result : results) {
const int relevance =
std::min(kMaxSearchResultScore, std::max(result->relevance, 0));
const GURL icon_url =
result->icon_url ? GURL(*result->icon_url.get()) : GURL();
app_list::LauncherSearchResult* search_result =
new app_list::LauncherSearchResult(result->item_id, icon_url, relevance,
profile_, extension,
error_reporter->Duplicate());
search_result->set_title(base::UTF8ToUTF16(result->title));
search_results.push_back(search_result);
}
provider_->SetSearchResults(extension->id(), search_results.Pass());
}
bool Service::IsQueryRunning() const {
return is_query_running_;
}
void Service::OnExtensionLoaded(content::BrowserContext* browser_context,
const extensions::Extension* extension) {
// Invalidate cache.
cached_listener_extension_ids_.reset();
}
void Service::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const extensions::Extension* extension,
extensions::UnloadedExtensionInfo::Reason reason) {
// Invalidate cache.
cached_listener_extension_ids_.reset();
}
void Service::CacheListenerExtensionIds() {
// If it's already cached, do nothing.
if (cached_listener_extension_ids_)
return;
cached_listener_extension_ids_.reset(new std::set<ExtensionId>());
const ExtensionSet& extension_set = extension_registry_->enabled_extensions();
for (scoped_refptr<const extensions::Extension> extension : extension_set) {
const extensions::PermissionsData* permission_data =
extension->permissions_data();
const bool has_permission = permission_data->HasAPIPermission(
extensions::APIPermission::kLauncherSearchProvider);
if (has_permission)
cached_listener_extension_ids_->insert(extension->id());
}
}
} // namespace launcher_search_provider
} // namespace chromeos