Commit fe7dbc90 authored by Qiang Xu's avatar Qiang Xu Committed by Commit Bot

arc: introduce personal contacts search to launcher

changes:
This CL relies on android CL: ag/3691606.
This CL introduces the framework of chrome side changes and also did
initial UI changes (circular 40px avatar icon) of contacts search
result.

Bug: 818902
Test: tested on device with android changes patched
Change-Id: Id9bb1e2a9c1a1c179f6ceef3abe7249fdad83a7c
Reviewed-on: https://chromium-review.googlesource.com/957421Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarLuis Hector Chavez <lhchavez@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Qiang Xu <warx@google.com>
Cr-Commit-Position: refs/heads/master@{#542883}
parent c47f6005
...@@ -3477,6 +3477,10 @@ split_static_library("ui") { ...@@ -3477,6 +3477,10 @@ split_static_library("ui") {
"app_list/search/app_result.h", "app_list/search/app_result.h",
"app_list/search/app_search_provider.cc", "app_list/search/app_search_provider.cc",
"app_list/search/app_search_provider.h", "app_list/search/app_search_provider.h",
"app_list/search/arc/arc_app_data_search_provider.cc",
"app_list/search/arc/arc_app_data_search_provider.h",
"app_list/search/arc/arc_app_data_search_result.cc",
"app_list/search/arc/arc_app_data_search_result.h",
"app_list/search/arc/arc_playstore_search_provider.cc", "app_list/search/arc/arc_playstore_search_provider.cc",
"app_list/search/arc/arc_playstore_search_provider.h", "app_list/search/arc/arc_playstore_search_provider.h",
"app_list/search/arc/arc_playstore_search_result.cc", "app_list/search/arc/arc_playstore_search_result.cc",
......
// Copyright 2018 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/arc/arc_app_data_search_provider.h"
#include <memory>
#include <utility>
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/ui/app_list/search/arc/arc_app_data_search_result.h"
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_service_manager.h"
#include "components/arc/connection_holder.h"
namespace app_list {
namespace {
// Checks if we're receiving a result with valid data from Android.
bool IsValidResult(const arc::mojom::AppDataResult& result) {
if (result.launch_intent_uri.empty() || result.label.empty())
return false;
return true;
}
} // namespace
ArcAppDataSearchProvider::ArcAppDataSearchProvider(
int max_results,
Profile* profile,
AppListControllerDelegate* list_controller)
: max_results_(max_results),
profile_(profile),
list_controller_(list_controller),
weak_ptr_factory_(this) {}
ArcAppDataSearchProvider::~ArcAppDataSearchProvider() = default;
void ArcAppDataSearchProvider::Start(const base::string16& query) {
arc::mojom::AppInstance* app_instance =
arc::ArcServiceManager::Get()
? ARC_GET_INSTANCE_FOR_METHOD(
arc::ArcServiceManager::Get()->arc_bridge_service()->app(),
GetIcingGlobalQueryResults)
: nullptr;
if (!app_instance || query.empty()) {
ClearResults();
return;
}
weak_ptr_factory_.InvalidateWeakPtrs();
app_instance->GetIcingGlobalQueryResults(
base::UTF16ToUTF8(query), max_results_,
base::BindOnce(&ArcAppDataSearchProvider::OnResults,
weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()));
}
void ArcAppDataSearchProvider::OnResults(
base::TimeTicks query_start_time,
arc::mojom::AppDataRequestState state,
std::vector<arc::mojom::AppDataResultPtr> results) {
if (state != arc::mojom::AppDataRequestState::REQUEST_SUCCESS) {
DCHECK(results.empty());
ClearResults();
return;
}
SearchProvider::Results new_results;
for (auto& result : results) {
if (!IsValidResult(*result)) {
ClearResults();
return;
}
new_results.emplace_back(std::make_unique<ArcAppDataSearchResult>(
std::move(result), profile_, list_controller_));
}
SwapResults(&new_results);
}
} // namespace app_list
// Copyright 2018 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_ARC_ARC_APP_DATA_SEARCH_PROVIDER_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_DATA_SEARCH_PROVIDER_H_
#include <vector>
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "chrome/browser/ui/app_list/search/search_provider.h"
#include "components/arc/common/app.mojom.h"
class Profile;
class AppListControllerDelegate;
namespace app_list {
class ArcAppDataSearchProvider : public SearchProvider {
public:
ArcAppDataSearchProvider(int max_results,
Profile* profile,
AppListControllerDelegate* list_controller);
~ArcAppDataSearchProvider() override;
// SearchProvider:
void Start(const base::string16& query) override;
private:
void OnResults(base::TimeTicks query_start_time,
arc::mojom::AppDataRequestState state,
std::vector<arc::mojom::AppDataResultPtr> results);
const int max_results_;
// |profile_| is owned by ProfileInfo.
Profile* const profile_;
// |list_controller_| is owned by AppListServiceAsh and lives until the
// service finishes.
AppListControllerDelegate* const list_controller_;
base::WeakPtrFactory<ArcAppDataSearchProvider> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ArcAppDataSearchProvider);
};
} // namespace app_list
#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_DATA_SEARCH_PROVIDER_H_
// Copyright 2018 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/arc/arc_app_data_search_result.h"
#include <utility>
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/app_list/app_list_controller_delegate.h"
#include "chrome/browser/ui/app_list/search/arc/icon_decode_request.h"
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_service_manager.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/path.h"
namespace app_list {
namespace {
constexpr char kAppDataSearchPrefix[] = "appdatasearch://";
constexpr int kAvatarSize = 40;
bool LaunchIntent(const std::string& intent_uri, int64_t display_id) {
auto* arc_service_manager = arc::ArcServiceManager::Get();
if (!arc_service_manager)
return false;
auto* app = arc_service_manager->arc_bridge_service()->app();
if (auto* app_instance = ARC_GET_INSTANCE_FOR_METHOD(app, LaunchIntent)) {
app_instance->LaunchIntent(intent_uri, display_id);
return true;
}
if (auto* app_instance =
ARC_GET_INSTANCE_FOR_METHOD(app, LaunchIntentDeprecated)) {
app_instance->LaunchIntentDeprecated(intent_uri, base::nullopt);
return true;
}
return false;
}
// Provide circular avatar image source.
class AvatarImageSource : public gfx::CanvasImageSource {
public:
AvatarImageSource(gfx::ImageSkia avatar, int size)
: CanvasImageSource(gfx::Size(size, size), false), radius_(size / 2) {
avatar_ = gfx::ImageSkiaOperations::CreateResizedImage(
avatar, skia::ImageOperations::RESIZE_BEST, gfx::Size(size, size));
}
~AvatarImageSource() override = default;
private:
// gfx::CanvasImageSource overrides:
void Draw(gfx::Canvas* canvas) override {
gfx::Path circular_mask;
circular_mask.addCircle(SkIntToScalar(radius_), SkIntToScalar(radius_),
SkIntToScalar(radius_));
canvas->ClipPath(circular_mask, true);
canvas->DrawImageInt(avatar_, 0, 0);
}
gfx::ImageSkia avatar_;
const int radius_;
DISALLOW_COPY_AND_ASSIGN(AvatarImageSource);
};
} // namespace
ArcAppDataSearchResult::ArcAppDataSearchResult(
arc::mojom::AppDataResultPtr data,
Profile* profile,
AppListControllerDelegate* list_controller)
: data_(std::move(data)),
profile_(profile),
list_controller_(list_controller),
weak_ptr_factory_(this) {
set_title(base::UTF8ToUTF16(label()));
set_id(kAppDataSearchPrefix + launch_intent_uri());
set_display_type(DISPLAY_TILE);
icon_decode_request_ = std::make_unique<IconDecodeRequest>(
base::BindOnce(&ArcAppDataSearchResult::SetIconToAvatarIcon,
weak_ptr_factory_.GetWeakPtr()));
ImageDecoder::StartWithOptions(icon_decode_request_.get(), icon_png_data(),
ImageDecoder::DEFAULT_CODEC, true,
gfx::Size());
}
ArcAppDataSearchResult::~ArcAppDataSearchResult() = default;
std::unique_ptr<SearchResult> ArcAppDataSearchResult::Duplicate() const {
std::unique_ptr<ArcAppDataSearchResult> result =
std::make_unique<ArcAppDataSearchResult>(data_.Clone(), profile_,
list_controller_);
result->SetIcon(icon());
return result;
}
ui::MenuModel* ArcAppDataSearchResult::GetContextMenuModel() {
// TODO(warx): Enable Context Menu.
return nullptr;
}
void ArcAppDataSearchResult::Open(int event_flags) {
LaunchIntent(launch_intent_uri(), list_controller_->GetAppListDisplayId());
}
void ArcAppDataSearchResult::SetIconToAvatarIcon(const gfx::ImageSkia& icon) {
SetIcon(gfx::ImageSkia(std::make_unique<AvatarImageSource>(icon, kAvatarSize),
gfx::Size(kAvatarSize, kAvatarSize)));
}
} // namespace app_list
// Copyright 2018 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_ARC_ARC_APP_DATA_SEARCH_RESULT_H_
#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_DATA_SEARCH_RESULT_H_
#include <memory>
#include <string>
#include <vector>
#include "ash/app_list/model/search/search_result.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "components/arc/common/app.mojom.h"
class AppListControllerDelegate;
class Profile;
namespace app_list {
class IconDecodeRequest;
class ArcAppDataSearchResult : public SearchResult {
public:
ArcAppDataSearchResult(arc::mojom::AppDataResultPtr data,
Profile* profile,
AppListControllerDelegate* list_controller);
~ArcAppDataSearchResult() override;
// app_list::SearchResult:
std::unique_ptr<SearchResult> Duplicate() const override;
ui::MenuModel* GetContextMenuModel() override;
void Open(int event_flags) override;
private:
const std::string& launch_intent_uri() const {
return data_->launch_intent_uri;
}
const std::string& label() const { return data_->label; }
const std::vector<uint8_t>& icon_png_data() const {
return data_->icon_png_data;
}
// Apply avatar style to |icon| and use it for SearchResult.
void SetIconToAvatarIcon(const gfx::ImageSkia& icon);
arc::mojom::AppDataResultPtr data_;
std::unique_ptr<IconDecodeRequest> icon_decode_request_;
// |profile_| is owned by ProfileInfo.
Profile* const profile_;
// |list_controller_| is owned by AppListServiceAsh and lives until the
// service finishes.
AppListControllerDelegate* const list_controller_;
base::WeakPtrFactory<ArcAppDataSearchResult> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ArcAppDataSearchResult);
};
} // namespace app_list
#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_DATA_SEARCH_RESULT_H_
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "ui/app_list/app_list_switches.h" #include "ui/app_list/app_list_switches.h"
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "chrome/browser/ui/app_list/search/arc/arc_app_data_search_provider.h"
#include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.h" #include "chrome/browser/ui/app_list/search/arc/arc_playstore_search_provider.h"
#endif #endif
...@@ -46,6 +47,8 @@ constexpr size_t kMaxLauncherSearchResults = 2; ...@@ -46,6 +47,8 @@ constexpr size_t kMaxLauncherSearchResults = 2;
// filter out more than half of results. // filter out more than half of results.
// TODO(753947): Consider progressive algorithm of getting Play Store results. // TODO(753947): Consider progressive algorithm of getting Play Store results.
constexpr size_t kMaxPlayStoreResults = 12; constexpr size_t kMaxPlayStoreResults = 12;
constexpr size_t kMaxAppDataResults = 6;
#endif #endif
} // namespace } // namespace
...@@ -114,6 +117,13 @@ std::unique_ptr<SearchController> CreateSearchController( ...@@ -114,6 +117,13 @@ std::unique_ptr<SearchController> CreateSearchController(
std::make_unique<ArcPlayStoreSearchProvider>(kMaxPlayStoreResults, std::make_unique<ArcPlayStoreSearchProvider>(kMaxPlayStoreResults,
profile, list_controller)); profile, list_controller));
} }
size_t app_data_api_group_id =
controller->AddGroup(kMaxAppDataResults, 1.0, 10.0);
controller->AddProvider(app_data_api_group_id,
std::make_unique<ArcAppDataSearchProvider>(
kMaxAppDataResults, profile, list_controller));
#endif #endif
return controller; return controller;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// Next MinVersion: 27 // Next MinVersion: 28
module arc.mojom; module arc.mojom;
...@@ -133,6 +133,40 @@ enum AppDiscoveryRequestState { ...@@ -133,6 +133,40 @@ enum AppDiscoveryRequestState {
PHONESKY_RESULT_INVALID_DATA = 16, PHONESKY_RESULT_INVALID_DATA = 16,
}; };
// Describes an app data search result.
struct AppDataResult {
// Intent uri to launch the result.
string launch_intent_uri;
// Label for the result.
string label;
// Icon information in png format.
array<uint8> icon_png_data;
};
// Describes the status of an app data search request, including completed
// states and all possible anomalies.
[Extensible]
enum AppDataRequestState {
// Request is handled successfully.
REQUEST_SUCCESS = 0,
// Request is canceled.
REQUEST_CANCELED = 1,
// Request times out.
REQUEST_TIMEOUT = 2,
// Request fails for the case of an interrupted status.
REQUEST_INTERRUPTED = 3,
// Request fails for the case of response document error.
RESPONSE_DOCUMENT_ERROR = 4,
// Request has an unexpected exception of call to GmsCore.
REQUEST_UNEXPECTED_EXCEPTION = 5,
// Request has invalid parameters.
REQUEST_HAS_INVALID_PARAMS = 6,
// AppDataSearchProxyService is not available.
APP_DATA_SEARCH_PROXY_NOT_AVAILABLE = 7,
// Failed to call globalQuery to GmsCore.
FAILED_TO_CALL_GLOBALQUERY = 8,
};
// Next method ID: 18 // Next method ID: 18
interface AppHost { interface AppHost {
// Sends newly added ARC app to Chrome. This message is sent when ARC receives // Sends newly added ARC app to Chrome. This message is sent when ARC receives
...@@ -219,7 +253,7 @@ interface AppHost { ...@@ -219,7 +253,7 @@ interface AppHost {
}; };
// TODO(lhchavez): Migrate all request/response messages to Mojo. // TODO(lhchavez): Migrate all request/response messages to Mojo.
// Next method ID: 22 // Next method ID: 23
interface AppInstance { interface AppInstance {
// DEPRECATED: Please use Init@21 instead. // DEPRECATED: Please use Init@21 instead.
InitDeprecated@0(AppHost host_ptr); InitDeprecated@0(AppHost host_ptr);
...@@ -307,4 +341,9 @@ interface AppInstance { ...@@ -307,4 +341,9 @@ interface AppInstance {
[MinVersion=20] GetRecentAndSuggestedAppsFromPlayStore@16( [MinVersion=20] GetRecentAndSuggestedAppsFromPlayStore@16(
string query, int32 max_results) => string query, int32 max_results) =>
(AppDiscoveryRequestState state@1, array<AppDiscoveryResult> results@0); (AppDiscoveryRequestState state@1, array<AppDiscoveryResult> results@0);
// Starts a query for app data, which is querying icing indexable contents.
[MinVersion=27] GetIcingGlobalQueryResults@22(
string query, int32 max_results) =>
(AppDataRequestState state, array<AppDataResult> results);
}; };
...@@ -341,6 +341,14 @@ void FakeAppInstance::GetRecentAndSuggestedAppsFromPlayStore( ...@@ -341,6 +341,14 @@ void FakeAppInstance::GetRecentAndSuggestedAppsFromPlayStore(
std::move(fake_apps)); std::move(fake_apps));
} }
void FakeAppInstance::GetIcingGlobalQueryResults(
const std::string& query,
int32_t max_results,
GetIcingGlobalQueryResultsCallback callback) {
std::move(callback).Run(arc::mojom::AppDataRequestState::REQUEST_SUCCESS,
std::vector<arc::mojom::AppDataResultPtr>());
}
void FakeAppInstance::StartPaiFlow() { void FakeAppInstance::StartPaiFlow() {
++start_pai_request_count_; ++start_pai_request_count_;
} }
......
...@@ -124,6 +124,10 @@ class FakeAppInstance : public mojom::AppInstance { ...@@ -124,6 +124,10 @@ class FakeAppInstance : public mojom::AppInstance {
const std::string& query, const std::string& query,
int32_t max_results, int32_t max_results,
GetRecentAndSuggestedAppsFromPlayStoreCallback callback) override; GetRecentAndSuggestedAppsFromPlayStoreCallback callback) override;
void GetIcingGlobalQueryResults(
const std::string& query,
int32_t max_results,
GetIcingGlobalQueryResultsCallback callback) override;
void StartPaiFlow() override; void StartPaiFlow() override;
// Methods to reply messages. // Methods to reply messages.
......
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