Commit 6f33fd10 authored by Lu Huang's avatar Lu Huang Committed by Commit Bot

Persist url_handlers info from web app manifest to WebAppDatabase.

design doc: https://docs.google.com/document/d/19dGklalQTRtRrG3PKrVbDRmYPLHGLnsGEwUaed7sAFQ/edit?usp=sharing

overview cl: https://chromium-review.googlesource.com/c/chromium/src/+/2393252

Chrome status: https://www.chromestatus.com/feature/5739732661174272

Bug: 1072058
Change-Id: I8a73e070d0121635be015239dc8f6c34a55fad97
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2461219
Commit-Queue: Lu Huang <luhua@microsoft.com>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Reviewed-by: default avatarMandy Chen <mandy.chen@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#827000}
parent 9fe1c3c5
......@@ -80,6 +80,7 @@ source_set("web_applications") {
"//components/keyed_service/content",
"//components/performance_manager",
"//components/pref_registry",
"//components/services/app_service/public/cpp:app_url_handling",
"//components/services/app_service/public/cpp:protocol_handling",
"//components/sync",
"//content/public/browser",
......@@ -209,6 +210,7 @@ source_set("web_applications_unit_tests") {
"//chrome/browser/web_applications/preinstalled_web_apps",
"//chrome/common",
"//chrome/test:test_support",
"//components/services/app_service/public/cpp:app_url_handling",
"//components/services/app_service/public/cpp:protocol_handling",
"//content/public/browser",
"//content/test:test_support",
......
......@@ -276,6 +276,8 @@ void UpdateWebAppInfoFromManifest(const blink::Manifest& manifest,
web_app_info->protocol_handlers = manifest.protocol_handlers;
web_app_info->url_handlers = manifest.url_handlers;
// If any shortcuts are specified in the manifest, they take precedence over
// any we picked up from the web_app stuff.
if (!manifest.shortcuts.empty() &&
......
......@@ -19,6 +19,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace web_app {
......@@ -109,6 +110,13 @@ TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest) {
manifest.protocol_handlers.push_back(protocol_handler);
}
{
blink::Manifest::UrlHandler url_handler;
url_handler.origin =
url::Origin::Create(GURL("https://url_handlers_origin.com/"));
manifest.url_handlers.push_back(url_handler);
}
UpdateWebAppInfoFromManifest(manifest, &web_app_info);
EXPECT_EQ(base::UTF8ToUTF16(kAppShortName), web_app_info.title);
EXPECT_EQ(AppUrl(), web_app_info.start_url);
......@@ -163,6 +171,11 @@ TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest) {
auto protocol_handler = web_app_info.protocol_handlers[0];
EXPECT_EQ(protocol_handler.protocol, base::UTF8ToUTF16("mailto"));
EXPECT_EQ(protocol_handler.url, GURL("http://example.com/handle=%s"));
EXPECT_EQ(1u, web_app_info.url_handlers.size());
auto url_handler = web_app_info.url_handlers[0];
EXPECT_EQ(url_handler.origin,
url::Origin::Create(GURL("https://url_handlers_origin.com/")));
}
TEST(WebAppInstallUtils, UpdateWebAppInfoFromManifest_EmptyName) {
......@@ -321,6 +334,13 @@ TEST_F(WebAppInstallUtilsWithShortcutsMenu,
manifest.protocol_handlers.push_back(protocol_handler);
}
{
blink::Manifest::UrlHandler url_handler;
url_handler.origin =
url::Origin::Create(GURL("https://url_handlers_origin.com/"));
manifest.url_handlers.push_back(url_handler);
}
UpdateWebAppInfoFromManifest(manifest, &web_app_info);
EXPECT_EQ(base::UTF8ToUTF16(kAppShortName), web_app_info.title);
EXPECT_EQ(AppUrl(), web_app_info.start_url);
......@@ -411,6 +431,12 @@ TEST_F(WebAppInstallUtilsWithShortcutsMenu,
auto protocol_handler = web_app_info.protocol_handlers[0];
EXPECT_EQ(protocol_handler.protocol, base::UTF8ToUTF16("mailto"));
EXPECT_EQ(protocol_handler.url, GURL("http://example.com/handle=%s"));
// Check URL handlers were updated
EXPECT_EQ(1u, web_app_info.url_handlers.size());
auto url_handler = web_app_info.url_handlers[0];
EXPECT_EQ(url_handler.origin,
url::Origin::Create(GURL("https://url_handlers_origin.com/")));
}
// Tests that we limit the number of icons declared by a site.
......
......@@ -182,6 +182,10 @@ struct WebApplicationInfo {
// The URL protocols/schemes that the app can handle.
std::vector<blink::Manifest::ProtocolHandler> protocol_handlers;
// The app intends to act as a URL handler for URLs described by this
// information.
std::vector<blink::Manifest::UrlHandler> url_handlers;
// User preference as to whether to auto run the app on OS login.
// Currently only supported in Windows platform.
bool run_on_os_login = false;
......
......@@ -32,6 +32,10 @@ message WebAppProtocolHandler {
required string url = 2;
}
message WebAppUrlHandlerProto {
required string origin = 1;
}
// A set to track simultaneous installs and uninstalls from multiple install
// sources.
message SourcesProto {
......@@ -160,4 +164,6 @@ message WebAppProto {
optional ShareTarget share_target = 25;
optional string launch_query_params = 26;
repeated WebAppUrlHandlerProto url_handlers = 27;
}
......@@ -237,6 +237,10 @@ void WebApp::SetProtocolHandlers(
protocol_handlers_ = std::move(handlers);
}
void WebApp::SetUrlHandlers(apps::UrlHandlers url_handlers) {
url_handlers_ = std::move(url_handlers);
}
void WebApp::SetShortcutsMenuItemInfos(
std::vector<WebApplicationShortcutsMenuItemInfo>
shortcuts_menu_item_infos) {
......@@ -340,6 +344,8 @@ std::ostream& operator<<(std::ostream& out, const WebApp& app) {
app.protocol_handlers_) {
out << " protocol_handler: " << protocol_handler << std::endl;
}
for (const apps::UrlHandlerInfo& url_handler : app.url_handlers_)
out << " url_handler: " << url_handler << std::endl;
out << " chromeos_data: " << app.chromeos_data_.has_value() << std::endl;
if (app.chromeos_data_.has_value())
......@@ -373,8 +379,9 @@ bool operator==(const WebApp& app1, const WebApp& app2) {
app1.is_locally_installed_, app1.is_in_sync_install_,
app1.file_handlers_, app1.share_target_,
app1.additional_search_terms_, app1.protocol_handlers_,
app1.sync_fallback_data_, app1.last_launch_time_,
app1.install_time_, app1.run_on_os_login_mode_) ==
app1.url_handlers_, app1.sync_fallback_data_,
app1.last_launch_time_, app1.install_time_,
app1.run_on_os_login_mode_) ==
std::tie(app2.app_id_, app2.sources_, app2.name_, app2.start_url_,
app2.launch_query_params_, app2.description_, app2.scope_,
app2.theme_color_, app2.background_color_, app2.icon_infos_,
......@@ -386,8 +393,9 @@ bool operator==(const WebApp& app1, const WebApp& app2) {
app2.is_locally_installed_, app2.is_in_sync_install_,
app2.file_handlers_, app2.share_target_,
app2.additional_search_terms_, app2.protocol_handlers_,
app2.sync_fallback_data_, app2.last_launch_time_,
app2.install_time_, app2.run_on_os_login_mode_);
app2.url_handlers_, app2.sync_fallback_data_,
app2.last_launch_time_, app2.install_time_,
app2.run_on_os_login_mode_);
}
bool operator!=(const WebApp& app1, const WebApp& app2) {
......
......@@ -18,6 +18,7 @@
#include "components/services/app_service/public/cpp/file_handler.h"
#include "components/services/app_service/public/cpp/protocol_handler_info.h"
#include "components/services/app_service/public/cpp/share_target.h"
#include "components/services/app_service/public/cpp/url_handler_info.h"
#include "components/sync/model/string_ordinal.h"
#include "third_party/skia/include/core/SkColor.h"
#include "url/gurl.h"
......@@ -118,6 +119,8 @@ class WebApp {
return protocol_handlers_;
}
const apps::UrlHandlers& url_handlers() const { return url_handlers_; }
RunOnOsLoginMode run_on_os_login_mode() const {
return run_on_os_login_mode_;
}
......@@ -203,6 +206,7 @@ class WebApp {
std::vector<std::string> additional_search_terms);
void SetProtocolHandlers(
std::vector<apps::ProtocolHandlerInfo> protocol_handlers);
void SetUrlHandlers(apps::UrlHandlers url_handlers);
void SetLastLaunchTime(const base::Time& time);
void SetInstallTime(const base::Time& time);
void SetRunOnOsLoginMode(RunOnOsLoginMode mode);
......@@ -254,6 +258,7 @@ class WebApp {
base::Time install_time_;
RunOnOsLoginMode run_on_os_login_mode_ = RunOnOsLoginMode::kUndefined;
SyncFallbackData sync_fallback_data_;
apps::UrlHandlers url_handlers_;
};
// For logging and debug purposes.
......
......@@ -28,6 +28,8 @@
#include "components/sync/model/metadata_change_list.h"
#include "components/sync/model/model_error.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace web_app {
......@@ -296,6 +298,11 @@ std::unique_ptr<WebAppProto> WebAppDatabase::CreateWebAppProto(
protocol_handler_proto->set_url(protocol_handler.url.spec());
}
for (const auto& url_handler : web_app.url_handlers()) {
WebAppUrlHandlerProto* url_handler_proto = local_data->add_url_handlers();
url_handler_proto->set_origin(url_handler.origin.Serialize());
}
return local_data;
}
......@@ -606,6 +613,21 @@ std::unique_ptr<WebApp> WebAppDatabase::CreateWebApp(
ToRunOnOsLoginMode(local_data.user_run_on_os_login_mode()));
}
std::vector<apps::UrlHandlerInfo> url_handlers;
for (const auto& url_handler_proto : local_data.url_handlers()) {
apps::UrlHandlerInfo url_handler;
url::Origin origin = url::Origin::Create(GURL(url_handler_proto.origin()));
if (origin.opaque()) {
DLOG(ERROR) << "WebApp UrlHandler proto url parse error: "
<< origin.GetDebugString();
return nullptr;
}
url_handler.origin = std::move(origin);
url_handlers.push_back(std::move(url_handler));
}
web_app->SetUrlHandlers(std::move(url_handlers));
return web_app;
}
......
......@@ -30,9 +30,11 @@
#include "components/services/app_service/public/cpp/file_handler.h"
#include "components/services/app_service/public/cpp/protocol_handler_info.h"
#include "components/services/app_service/public/cpp/share_target.h"
#include "components/services/app_service/public/cpp/url_handler_info.h"
#include "components/sync/model/model_type_store.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace web_app {
......@@ -145,6 +147,22 @@ class WebAppDatabaseTest : public WebAppTest {
return protocol_handlers;
}
static std::vector<apps::UrlHandlerInfo> CreateUrlHandlers(uint32_t suffix) {
std::vector<apps::UrlHandlerInfo> url_handlers;
for (unsigned int i = 0; i < 3; ++i) {
std::string suffix_str =
base::NumberToString(suffix) + base::NumberToString(i);
apps::UrlHandlerInfo url_handler;
url_handler.origin =
url::Origin::Create(GURL("https://app-" + suffix_str + ".com/"));
url_handlers.push_back(std::move(url_handler));
}
return url_handlers;
}
static std::vector<WebApplicationShortcutsMenuItemInfo>
CreateShortcutsMenuItemInfos(const std::string& base_url, uint32_t suffix) {
std::vector<WebApplicationShortcutsMenuItemInfo> shortcuts_menu_item_infos;
......@@ -283,6 +301,7 @@ class WebAppDatabaseTest : public WebAppTest {
if (random.next_bool())
app->SetShareTarget(CreateShareTarget(random.next_uint()));
app->SetProtocolHandlers(CreateProtocolHandlers(random.next_uint()));
app->SetUrlHandlers(CreateUrlHandlers(random.next_uint()));
const int num_additional_search_terms = random.next_uint(8);
std::vector<std::string> additional_search_terms(
......@@ -576,6 +595,7 @@ TEST_F(WebAppDatabaseTest, WebAppWithoutOptionalFields) {
EXPECT_FALSE(app->share_target().has_value());
EXPECT_TRUE(app->additional_search_terms().empty());
EXPECT_TRUE(app->protocol_handlers().empty());
EXPECT_TRUE(app->url_handlers().empty());
EXPECT_TRUE(app->last_launch_time().is_null());
EXPECT_TRUE(app->install_time().is_null());
EXPECT_TRUE(app->shortcuts_menu_item_infos().empty());
......@@ -632,7 +652,7 @@ TEST_F(WebAppDatabaseTest, WebAppWithoutOptionalFields) {
EXPECT_TRUE(app_copy->file_handlers().empty());
EXPECT_FALSE(app_copy->share_target().has_value());
EXPECT_TRUE(app_copy->additional_search_terms().empty());
EXPECT_TRUE(app_copy->protocol_handlers().empty());
EXPECT_TRUE(app_copy->url_handlers().empty());
EXPECT_TRUE(app_copy->shortcuts_menu_item_infos().empty());
EXPECT_TRUE(app_copy->downloaded_shortcuts_menu_icons_sizes().empty());
EXPECT_EQ(app_copy->run_on_os_login_mode(), RunOnOsLoginMode::kUndefined);
......
......@@ -85,6 +85,19 @@ void SetWebAppProtocolHandlers(
web_app.SetProtocolHandlers(web_app_protocol_handlers);
}
void SetWebAppUrlHandlers(
const std::vector<blink::Manifest::UrlHandler>& url_handlers,
WebApp& web_app) {
apps::UrlHandlers web_app_url_handlers;
for (const auto& url_handler : url_handlers) {
apps::UrlHandlerInfo web_app_url_handler;
web_app_url_handler.origin = url_handler.origin;
web_app_url_handlers.push_back(std::move(web_app_url_handler));
}
web_app.SetUrlHandlers(std::move(web_app_url_handlers));
}
} // namespace
void SetWebAppManifestFields(const WebApplicationInfo& web_app_info,
......@@ -129,6 +142,7 @@ void SetWebAppManifestFields(const WebApplicationInfo& web_app_info,
SetWebAppFileHandlers(web_app_info.file_handlers, web_app);
web_app.SetShareTarget(web_app_info.share_target);
SetWebAppProtocolHandlers(web_app_info.protocol_handlers, web_app);
SetWebAppUrlHandlers(web_app_info.url_handlers, web_app);
if (base::FeatureList::IsEnabled(features::kDesktopPWAsRunOnOsLogin) &&
web_app_info.run_on_os_login) {
......
......@@ -47,6 +47,15 @@ component("app_update") {
]
}
source_set("app_url_handling") {
sources = [
"url_handler_info.cc",
"url_handler_info.h",
]
deps = [ "//url" ]
}
if (is_chromeos) {
source_set("instance_update") {
sources = [
......
// Copyright 2020 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 "components/services/app_service/public/cpp/url_handler_info.h"
namespace apps {
UrlHandlerInfo::UrlHandlerInfo() = default;
UrlHandlerInfo::UrlHandlerInfo(const UrlHandlerInfo&) = default;
UrlHandlerInfo& UrlHandlerInfo::operator=(const UrlHandlerInfo&) = default;
UrlHandlerInfo::UrlHandlerInfo(UrlHandlerInfo&&) = default;
UrlHandlerInfo& UrlHandlerInfo::operator=(UrlHandlerInfo&&) = default;
UrlHandlerInfo::~UrlHandlerInfo() = default;
bool operator==(const UrlHandlerInfo& handler1,
const UrlHandlerInfo& handler2) {
return handler1.origin == handler2.origin;
}
bool operator!=(const UrlHandlerInfo& handler1,
const UrlHandlerInfo& handler2) {
return !(handler1 == handler2);
}
std::ostream& operator<<(std::ostream& out, const UrlHandlerInfo& handler) {
out << "origin: " << handler.origin;
return out;
}
} // namespace apps
// Copyright 2020 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 COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_URL_HANDLER_INFO_H_
#define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_URL_HANDLER_INFO_H_
#include <ostream>
#include <vector>
#include "url/origin.h"
namespace apps {
// Contains information about a web app's URL handler information derived from
// its web app manifest.
struct UrlHandlerInfo {
UrlHandlerInfo();
// Copyable to support web_app::WebApp being copyable as it has a UrlHandlers
// member variable.
UrlHandlerInfo(const UrlHandlerInfo&);
UrlHandlerInfo& operator=(const UrlHandlerInfo&);
// Movable to support being contained in std::vector, which requires value
// types to be copyable or movable.
UrlHandlerInfo(UrlHandlerInfo&&);
UrlHandlerInfo& operator=(UrlHandlerInfo&&);
~UrlHandlerInfo();
url::Origin origin;
};
using UrlHandlers = std::vector<UrlHandlerInfo>;
bool operator==(const UrlHandlerInfo& url_handler1,
const UrlHandlerInfo& url_handler2);
bool operator!=(const UrlHandlerInfo& url_handler1,
const UrlHandlerInfo& url_handler2);
std::ostream& operator<<(std::ostream& out,
const UrlHandlerInfo& url_handler_info);
} // namespace apps
#endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_URL_HANDLER_INFO_H_
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