1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service.h"
7 #include "base/memory/scoped_vector.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/chromeos/launcher_search_provider/launcher_search_provider_service_factory.h"
10 #include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_provider.h"
11 #include "chrome/browser/ui/app_list/search/launcher_search/launcher_search_result.h"
12 #include "extensions/browser/extension_registry.h"
13 #include "extensions/common/extension_set.h"
14 #include "extensions/common/permissions/permissions_data.h"
16 namespace api_launcher_search_provider
=
17 extensions::api::launcher_search_provider
;
18 using extensions::ExtensionId
;
19 using extensions::ExtensionSet
;
22 namespace launcher_search_provider
{
24 Service::Service(Profile
* profile
,
25 extensions::ExtensionRegistry
* extension_registry
)
27 extension_registry_(extension_registry
),
30 is_query_running_(false) {
31 extension_registry_
->AddObserver(this);
35 extension_registry_
->RemoveObserver(this);
39 Service
* Service::Get(content::BrowserContext
* context
) {
40 return ServiceFactory::Get(context
);
43 void Service::OnQueryStarted(app_list::LauncherSearchProvider
* provider
,
44 const std::string
& query
,
45 const int max_result
) {
46 DCHECK(!is_query_running_
);
47 is_query_running_
= true;
52 extensions::EventRouter
* event_router
=
53 extensions::EventRouter::Get(profile_
);
55 CacheListenerExtensionIds();
56 for (const ExtensionId extension_id
: *cached_listener_extension_ids_
.get()) {
57 // Convert query_id_ to string here since queryId is defined as string in
58 // javascript side API while we use uint32 internally to generate it.
59 event_router
->DispatchEventToExtension(
61 make_scoped_ptr(new extensions::Event(
62 extensions::events::LAUNCHER_SEARCH_PROVIDER_ON_QUERY_STARTED
,
63 api_launcher_search_provider::OnQueryStarted::kEventName
,
64 api_launcher_search_provider::OnQueryStarted::Create(
65 query_id_
, query
, max_result
))));
69 void Service::OnQueryEnded() {
70 DCHECK(is_query_running_
);
73 extensions::EventRouter
* event_router
=
74 extensions::EventRouter::Get(profile_
);
76 CacheListenerExtensionIds();
77 for (const ExtensionId extension_id
: *cached_listener_extension_ids_
.get()) {
78 event_router
->DispatchEventToExtension(
80 make_scoped_ptr(new extensions::Event(
81 extensions::events::LAUNCHER_SEARCH_PROVIDER_ON_QUERY_ENDED
,
82 api_launcher_search_provider::OnQueryEnded::kEventName
,
83 api_launcher_search_provider::OnQueryEnded::Create(query_id_
))));
86 is_query_running_
= false;
89 void Service::OnOpenResult(const ExtensionId
& extension_id
,
90 const std::string
& item_id
) {
91 CacheListenerExtensionIds();
92 CHECK(ContainsValue(*cached_listener_extension_ids_
.get(), extension_id
));
94 extensions::EventRouter
* event_router
=
95 extensions::EventRouter::Get(profile_
);
96 event_router
->DispatchEventToExtension(
98 make_scoped_ptr(new extensions::Event(
99 extensions::events::LAUNCHER_SEARCH_PROVIDER_ON_OPEN_RESULT
,
100 api_launcher_search_provider::OnOpenResult::kEventName
,
101 api_launcher_search_provider::OnOpenResult::Create(item_id
))));
104 void Service::SetSearchResults(
105 const extensions::Extension
* extension
,
106 scoped_ptr
<ErrorReporter
> error_reporter
,
108 const std::vector
<linked_ptr
<
109 extensions::api::launcher_search_provider::SearchResult
>>& results
) {
110 // If query is not running or query_id is different from current query id,
111 // discard the results.
112 if (!is_query_running_
|| query_id
!= query_id_
)
115 // If |extension| is not in the listener extensions list, ignore it.
116 CacheListenerExtensionIds();
117 if (!ContainsValue(*cached_listener_extension_ids_
.get(), extension
->id()))
120 // Set search results to provider.
122 ScopedVector
<app_list::LauncherSearchResult
> search_results
;
123 for (const auto& result
: results
) {
124 const int relevance
=
125 std::min(kMaxSearchResultScore
, std::max(result
->relevance
, 0));
126 const GURL icon_url
=
127 result
->icon_url
? GURL(*result
->icon_url
.get()) : GURL();
129 app_list::LauncherSearchResult
* search_result
=
130 new app_list::LauncherSearchResult(result
->item_id
, icon_url
, relevance
,
132 error_reporter
->Duplicate());
133 search_result
->set_title(base::UTF8ToUTF16(result
->title
));
134 search_results
.push_back(search_result
);
136 provider_
->SetSearchResults(extension
->id(), search_results
.Pass());
139 bool Service::IsQueryRunning() const {
140 return is_query_running_
;
143 void Service::OnExtensionLoaded(content::BrowserContext
* browser_context
,
144 const extensions::Extension
* extension
) {
146 cached_listener_extension_ids_
.reset();
149 void Service::OnExtensionUnloaded(
150 content::BrowserContext
* browser_context
,
151 const extensions::Extension
* extension
,
152 extensions::UnloadedExtensionInfo::Reason reason
) {
154 cached_listener_extension_ids_
.reset();
157 void Service::CacheListenerExtensionIds() {
158 // If it's already cached, do nothing.
159 if (cached_listener_extension_ids_
)
162 cached_listener_extension_ids_
.reset(new std::set
<ExtensionId
>());
164 const ExtensionSet
& extension_set
= extension_registry_
->enabled_extensions();
165 for (scoped_refptr
<const extensions::Extension
> extension
: extension_set
) {
166 const extensions::PermissionsData
* permission_data
=
167 extension
->permissions_data();
168 const bool has_permission
= permission_data
->HasAPIPermission(
169 extensions::APIPermission::kLauncherSearchProvider
);
171 cached_listener_extension_ids_
->insert(extension
->id());
175 } // namespace launcher_search_provider
176 } // namespace chromeos