Commit 6bbf53d7 authored by yawano's avatar yawano Committed by Commit bot

Implement setSearchResults.

Initial implementation of chrome.launcherSearchProvider.setSearchResults.
iconUrl is not supported with this CL. It will be implemented with another CL.

BUG=440649

Review URL: https://codereview.chromium.org/1071093002

Cr-Commit-Position: refs/heads/master@{#325428}
parent 73d097cb
......@@ -4,6 +4,9 @@
#include "chrome/browser/chromeos/extensions/launcher_search_provider.h"
#include "chrome/browser/chromeos/launcher_search_provider/service.h"
#include "chrome/common/extensions/api/launcher_search_provider.h"
namespace extensions {
LauncherSearchProviderSetSearchResultsFunction::
......@@ -11,9 +14,15 @@ LauncherSearchProviderSetSearchResultsFunction::
}
bool LauncherSearchProviderSetSearchResultsFunction::RunSync() {
// TODO(yawano): Implement this (crbug.com/440649).
NOTREACHED();
return false;
using chromeos::launcher_search_provider::Service;
using extensions::api::launcher_search_provider::SetSearchResults::Params;
const scoped_ptr<Params> params(Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
Service* const service = Service::Get(GetProfile());
service->SetSearchResults(extension(), params->query_id, params->results);
return true;
}
} // namespace extensions
......@@ -4,8 +4,11 @@
#include "chrome/browser/chromeos/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/service_factory.h"
#include "chrome/common/extensions/api/launcher_search_provider.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"
......@@ -22,6 +25,7 @@ Service::Service(Profile* profile,
extensions::ExtensionRegistry* extension_registry)
: profile_(profile),
extension_registry_(extension_registry),
provider_(nullptr),
query_id_(0),
is_query_running_(false) {
}
......@@ -34,9 +38,12 @@ Service* Service::Get(content::BrowserContext* context) {
return ServiceFactory::Get(context);
}
void Service::OnQueryStarted(const std::string& query, const int max_result) {
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_;
......@@ -45,6 +52,9 @@ void Service::OnQueryStarted(const std::string& query, const int max_result) {
std::set<ExtensionId> extension_ids = GetListenerExtensionIds();
for (const ExtensionId extension_id : extension_ids) {
// Convert query_id_ to string here since queryId is defined as string in
// javascript side API while we use uint32 internally to generate it.
// TODO(yawano): Consider if we can change it to integer at javascript side.
event_router->DispatchEventToExtension(
extension_id,
make_scoped_ptr(new extensions::Event(
......@@ -56,6 +66,7 @@ void Service::OnQueryStarted(const std::string& query, const int max_result) {
void Service::OnQueryEnded() {
DCHECK(is_query_running_);
provider_ = nullptr;
extensions::EventRouter* event_router =
extensions::EventRouter::Get(profile_);
......@@ -73,6 +84,34 @@ void Service::OnQueryEnded() {
is_query_running_ = false;
}
void Service::SetSearchResults(
const extensions::Extension* extension,
const std::string& 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 != std::to_string(query_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);
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_;
}
......
......@@ -6,14 +6,23 @@
#define CHROME_BROWSER_CHROMEOS_LAUNCHER_SEARCH_PROVIDER_SERVICE_H_
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/launcher_search_provider.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/extension.h"
namespace app_list {
class LauncherSearchProvider;
} // namespace app_list
namespace chromeos {
namespace launcher_search_provider {
// Relevance score should be provided in a range from 0 to 4. 0 is the lowest
// relevance, 4 is the highest.
const int kMaxSearchResultScore = 4;
// Manages listener extensions and routes events. Listener extensions are
// extensions which are allowed to use this API. When this API becomes public,
// this API is white listed for file manager, and opt-in for other extensions.
......@@ -27,11 +36,20 @@ class Service : public KeyedService {
static Service* Get(content::BrowserContext* context);
// Dispatches onQueryStarted events to listener extensions.
void OnQueryStarted(const std::string& query, const int max_result);
void OnQueryStarted(app_list::LauncherSearchProvider* provider,
const std::string& query,
const int max_result);
// Dispatches onQueryEnded events to listener extensions.
void OnQueryEnded();
// Sets search results of a listener extension.
void SetSearchResults(
const extensions::Extension* extension,
const std::string& query_id,
const std::vector<linked_ptr<
extensions::api::launcher_search_provider::SearchResult>>& results);
// Returns true if there is a running query.
bool IsQueryRunning() const;
......@@ -41,6 +59,7 @@ class Service : public KeyedService {
Profile* const profile_;
extensions::ExtensionRegistry* extension_registry_;
app_list::LauncherSearchProvider* provider_;
uint32 query_id_;
bool is_query_running_;
......
......@@ -4,6 +4,7 @@
#include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/launcher_search_provider/service.h"
......@@ -19,7 +20,9 @@ const int kLauncherSearchProviderMaxResults = 6;
} // namespace
LauncherSearchProvider::LauncherSearchProvider(Profile* profile)
: profile_(profile), weak_ptr_factory_(this) {
: extension_results_deleter_(&extension_results_),
profile_(profile),
weak_ptr_factory_(this) {
}
LauncherSearchProvider::~LauncherSearchProvider() {
......@@ -36,6 +39,9 @@ void LauncherSearchProvider::Stop() {
// order not to start query after Stop() is called.
query_timer_.Stop();
// Clear all search results of the previous query.
STLDeleteValues(&extension_results_);
Service* service = Service::Get(profile_);
// Since we delay queries and filter out empty string queries, it can happen
......@@ -44,6 +50,29 @@ void LauncherSearchProvider::Stop() {
service->OnQueryEnded();
}
void LauncherSearchProvider::SetSearchResults(
const extensions::ExtensionId& extension_id,
ScopedVector<LauncherSearchResult> results) {
DCHECK(Service::Get(profile_)->IsQueryRunning());
// If it already has the results of this extension, delete it first.
if (ContainsKey(extension_results_, extension_id)) {
delete extension_results_[extension_id];
extension_results_.erase(extension_id);
}
// Add this extension's results.
extension_results_.insert(std::make_pair(
extension_id, new ScopedVector<LauncherSearchResult>(results.Pass())));
// Update results with other extension results.
ClearResults();
for (const auto& item : extension_results_) {
for (const auto* result : *item.second)
Add(result->Duplicate());
}
}
void LauncherSearchProvider::DelayQuery(const base::Closure& closure) {
base::TimeDelta delay =
base::TimeDelta::FromMilliseconds(kLauncherSearchProviderQueryDelayInMs);
......@@ -58,7 +87,7 @@ void LauncherSearchProvider::DelayQuery(const base::Closure& closure) {
void LauncherSearchProvider::StartInternal(const base::string16& query) {
if (!query.empty()) {
Service::Get(profile_)->OnQueryStarted(base::UTF16ToUTF8(query),
Service::Get(profile_)->OnQueryStarted(this, base::UTF16ToUTF8(query),
kLauncherSearchProviderMaxResults);
}
}
......
......@@ -5,10 +5,14 @@
#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_LAUNCHER_SEARCH_LAUNCHER_SEARCH_PROVIDER_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_LAUNCHER_SEARCH_LAUNCHER_SEARCH_PROVIDER_H_
#include "base/memory/scoped_vector.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h"
#include "extensions/common/extension.h"
#include "ui/app_list/search_provider.h"
namespace app_list {
......@@ -22,6 +26,8 @@ class LauncherSearchProvider : public SearchProvider {
void Start(bool is_voice_query, const base::string16& query) override;
void Stop() override;
void SetSearchResults(const extensions::ExtensionId& extension_id,
ScopedVector<LauncherSearchResult> extension_results);
private:
// Delays query for |kLauncherSearchProviderQueryDelayInMs|. This dispatches
......@@ -31,13 +37,21 @@ class LauncherSearchProvider : public SearchProvider {
// Dispatches |query| to LauncherSearchProvider service.
void StartInternal(const base::string16& query);
// The search results of each extension. The STLValueDeleter will
// automatically free the vectors in this map, but elements that are
// individually erased or replaced must be manually deleted.
typedef std::map<extensions::ExtensionId, ScopedVector<LauncherSearchResult>*>
ExtensionResults;
ExtensionResults extension_results_;
STLValueDeleter<ExtensionResults> extension_results_deleter_;
// A timer to delay query.
base::OneShotTimer<LauncherSearchProvider> query_timer_;
// The timestamp of the last query.
base::Time last_query_time_;
// Keep reference to profile to get LauncherSearchProvider service.
// The reference to profile to get LauncherSearchProvider service.
Profile* profile_;
base::WeakPtrFactory<LauncherSearchProvider> weak_ptr_factory_;
......
// 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/ui/app_list/search/launcher_search/launcher_search_result.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/launcher_search_provider/service.h"
#include "chrome/browser/extensions/extension_util.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
namespace {
const char kResultIdDelimiter = ':';
} // namespace
namespace app_list {
LauncherSearchResult::LauncherSearchResult(
const std::string& item_id,
const GURL& icon_url,
const int discrete_value_relevance,
Profile* profile,
const extensions::Extension* extension)
: item_id_(item_id),
discrete_value_relevance_(discrete_value_relevance),
profile_(profile),
extension_(extension) {
DCHECK_GE(discrete_value_relevance, 0);
DCHECK_LE(discrete_value_relevance,
chromeos::launcher_search_provider::kMaxSearchResultScore);
// TODO(yawano) Decode passed icon url and show it badged with extension
// icon.
extension_icon_image_.reset(new extensions::IconImage(
profile, extension, extensions::IconsInfo::GetIcons(extension),
GetPreferredIconDimension(), extensions::util::GetDefaultExtensionIcon(),
nullptr));
Initialize();
}
LauncherSearchResult::~LauncherSearchResult() {
if (extension_icon_image_ != nullptr)
extension_icon_image_->RemoveObserver(this);
}
scoped_ptr<SearchResult> LauncherSearchResult::Duplicate() const {
LauncherSearchResult* duplicated_result =
new LauncherSearchResult(item_id_, discrete_value_relevance_, profile_,
extension_, extension_icon_image_);
duplicated_result->set_title(title());
return make_scoped_ptr(duplicated_result);
}
void LauncherSearchResult::OnExtensionIconImageChanged(
extensions::IconImage* image) {
DCHECK_EQ(image, extension_icon_image_.get());
UpdateIcon();
}
LauncherSearchResult::LauncherSearchResult(
const std::string& item_id,
const int discrete_value_relevance,
Profile* profile,
const extensions::Extension* extension,
const linked_ptr<extensions::IconImage>& extension_icon_image)
: item_id_(item_id),
discrete_value_relevance_(discrete_value_relevance),
profile_(profile),
extension_(extension),
extension_icon_image_(extension_icon_image) {
DCHECK(extension_icon_image_ != nullptr);
Initialize();
}
void LauncherSearchResult::Initialize() {
set_id(GetSearchResultId());
set_relevance(static_cast<double>(discrete_value_relevance_) /
static_cast<double>(
chromeos::launcher_search_provider::kMaxSearchResultScore));
set_details(base::UTF8ToUTF16(extension_->name()));
extension_icon_image_->AddObserver(this);
UpdateIcon();
}
void LauncherSearchResult::UpdateIcon() {
if (!extension_icon_image_->image_skia().isNull())
SetIcon(extension_icon_image_->image_skia());
}
std::string LauncherSearchResult::GetSearchResultId() {
return extension_->id() + kResultIdDelimiter + item_id_;
}
} // namespace app_list
// 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.
#ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_LAUNCHER_SEARCH_LAUNCHER_SEARCH_RESULT_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_LAUNCHER_SEARCH_LAUNCHER_SEARCH_RESULT_H_
#include <string>
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/profiles/profile.h"
#include "extensions/browser/extension_icon_image.h"
#include "extensions/common/extension.h"
#include "ui/app_list/search_result.h"
#include "url/gurl.h"
namespace app_list {
class LauncherSearchResult : public SearchResult,
public extensions::IconImage::Observer {
public:
LauncherSearchResult(const std::string& item_id,
const GURL& icon_url,
const int discrete_value_relevance,
Profile* profile,
const extensions::Extension* extension);
~LauncherSearchResult() override;
scoped_ptr<SearchResult> Duplicate() const override;
void OnExtensionIconImageChanged(extensions::IconImage* image) override;
private:
// Constructor for duplicating a result.
LauncherSearchResult(
const std::string& item_id,
const int discrete_value_relevance,
Profile* profile,
const extensions::Extension* extension,
const linked_ptr<extensions::IconImage>& extension_icon_image);
void Initialize();
void UpdateIcon();
// Returns search result ID. The search result ID is comprised of the
// extension ID and the extension-supplied item ID. This is to avoid naming
// collisions for results of different extensions.
std::string GetSearchResultId();
const std::string item_id_;
// Must be between 0 and kMaxSearchResultScore.
const int discrete_value_relevance_;
Profile* profile_;
const extensions::Extension* extension_;
linked_ptr<extensions::IconImage> extension_icon_image_;
DISALLOW_COPY_AND_ASSIGN(LauncherSearchResult);
};
} // namespace app_list
#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_LAUNCHER_SEARCH_LAUNCHER_SEARCH_RESULT_H_
......@@ -707,9 +707,11 @@
# ChromeOS-only sources that don't end in _chromeos or live in a chromeos
# directory.
'chrome_browser_ui_chromeos_sources': [
# On chromeos, file manager extension handles the file open/save dialog.
'browser/ui/app_list/search/launcher_search/launcher_search_provider.cc',
'browser/ui/app_list/search/launcher_search/launcher_search_provider.h',
'browser/ui/app_list/search/launcher_search/launcher_search_result.cc',
'browser/ui/app_list/search/launcher_search/launcher_search_result.h',
# On chromeos, file manager extension handles the file open/save dialog.
'browser/ui/views/select_file_dialog_extension.cc',
'browser/ui/views/select_file_dialog_extension.h',
'browser/ui/views/select_file_dialog_extension_factory.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment