Commit d3492ce6 authored by Eric Willigers's avatar Eric Willigers Committed by Chromium LUCI CQ

Web Share Target for Chrome OS: Receive title, text, url

NavigateParamsForShareTarget() is moved to share_target_utils.h/cc

We read the shared title from the Intent shared_title.

We split the Intent's shared_text into text and url. See
https://chromium-review.googlesource.com/c/chromium/src/+/2569329

Not yet implemented:
Receiving title/text/url without files, for example using GET.

Design doc in progress:
https://docs.google.com/document/d/1E4CYASFDVNqmyCbaxa8u8sOn0-Sc1miLeZfA3t3ou5o/edit?usp=sharing

Bug: 1125880
Change-Id: I2920e96517b9432ef10f11610b08fb60fb9207d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2581636
Commit-Queue: Eric Willigers <ericwilligers@chromium.org>
Auto-Submit: Eric Willigers <ericwilligers@chromium.org>
Reviewed-by: default avatarAlan Cutter <alancutter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#836109}
parent f491e757
...@@ -4469,6 +4469,8 @@ static_library("ui") { ...@@ -4469,6 +4469,8 @@ static_library("ui") {
"views/extensions/settings_overridden_dialog_view.h", "views/extensions/settings_overridden_dialog_view.h",
"web_applications/app_browser_controller.cc", "web_applications/app_browser_controller.cc",
"web_applications/app_browser_controller.h", "web_applications/app_browser_controller.h",
"web_applications/share_target_utils.cc",
"web_applications/share_target_utils.h",
"web_applications/system_web_app_ui_utils.cc", "web_applications/system_web_app_ui_utils.cc",
"web_applications/system_web_app_ui_utils.h", "web_applications/system_web_app_ui_utils.h",
"web_applications/web_app_browser_controller.cc", "web_applications/web_app_browser_controller.cc",
......
// 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 "chrome/browser/ui/web_applications/share_target_utils.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/web_share_target/target_util.h"
#include "components/services/app_service/public/cpp/share_target.h"
#include "extensions/common/constants.h"
#include "net/base/mime_util.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_url.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#endif
namespace web_app {
bool SharedField::operator==(const SharedField& other) const {
return name == other.name && value == other.value;
}
std::vector<SharedField> ExtractSharedFields(
const apps::ShareTarget& share_target,
const apps::mojom::Intent& intent) {
std::vector<SharedField> result;
if (!share_target.params.title.empty() && intent.share_title.has_value()) {
result.push_back(
{.name = share_target.params.title, .value = *intent.share_title});
}
if (!intent.share_text.has_value())
return result;
std::string extracted_text = *intent.share_text;
GURL extracted_url;
size_t last_space = extracted_text.find_last_of(' ');
if (last_space == std::string::npos) {
extracted_url = GURL(extracted_text);
if (extracted_url.is_valid())
extracted_text.clear();
} else {
extracted_url = GURL(extracted_text.substr(last_space + 1));
if (extracted_url.is_valid())
extracted_text.erase(last_space);
}
if (!share_target.params.text.empty() && !extracted_text.empty())
result.push_back(
{.name = share_target.params.text, .value = extracted_text});
if (!share_target.params.url.empty() && extracted_url.is_valid())
result.push_back(
{.name = share_target.params.url, .value = extracted_url.spec()});
return result;
}
NavigateParams NavigateParamsForShareTarget(
Browser* browser,
const apps::ShareTarget& share_target,
const apps::mojom::Intent& intent) {
NavigateParams nav_params(browser, share_target.action,
ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
#if BUILDFLAG(IS_CHROMEOS_ASH)
std::vector<std::string> names;
std::vector<std::string> values;
std::vector<std::string> filenames;
std::vector<std::string> types;
std::vector<bool> is_value_file_uris;
DCHECK(intent.mime_type.has_value());
DCHECK(intent.file_urls.has_value());
const std::string& mime_type = intent.mime_type.value();
std::string name;
for (const apps::ShareTarget::Files& files : share_target.params.files) {
// Filter on MIME types. Chrome OS does not filter on file extensions.
// https://w3c.github.io/web-share-target/level-2/#dfn-accepted
if (base::ranges::any_of(files.accept, [&mime_type](const auto& criteria) {
return !base::StartsWith(criteria, ".") &&
net::MatchesMimeType(criteria, mime_type);
})) {
name = files.name;
break;
}
}
if (name.empty()) {
VLOG(1) << "Received unexpected MIME type: " << mime_type;
} else {
// Files for Web Share intents are created by the browser in
// a .WebShare directory, with generated file names and file urls - see
// //chrome/browser/webshare/chromeos/sharesheet_client.cc
for (const GURL& file_url : intent.file_urls.value()) {
storage::FileSystemContext* file_system_context =
file_manager::util::GetFileSystemContextForExtensionId(
browser->profile(), extension_misc::kFilesManagerAppId);
storage::FileSystemURL file_system_url =
file_system_context->CrackURL(file_url);
if (!file_system_url.is_valid()) {
VLOG(1) << "Received unexpected file URL: " << file_url.spec();
continue;
}
names.push_back(name);
values.push_back(file_system_url.path().AsUTF8Unsafe());
filenames.push_back(file_system_url.path().BaseName().AsUTF8Unsafe());
types.push_back(mime_type);
is_value_file_uris.push_back(true);
}
}
std::vector<SharedField> shared_fields =
ExtractSharedFields(share_target, intent);
for (const auto& shared_field : shared_fields) {
names.push_back(shared_field.name);
values.push_back(shared_field.value);
filenames.push_back(std::string());
types.push_back("text/plain");
is_value_file_uris.push_back(false);
}
const std::string boundary = net::GenerateMimeMultipartBoundary();
const std::string header_list = base::StringPrintf(
"Content-Type: multipart/form-data; boundary=%s\r\n", boundary.c_str());
scoped_refptr<network::ResourceRequestBody> post_data =
web_share_target::ComputeMultipartBody(names, values, is_value_file_uris,
filenames, types, boundary);
nav_params.post_data = post_data;
nav_params.extra_headers = header_list;
#else
// TODO(crbug.com/1153194): Support Web Share Target on Windows.
// TODO(crbug.com/1153195): Support Web Share Target on Mac.
NOTIMPLEMENTED();
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
return nav_params;
}
} // namespace web_app
// 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 CHROME_BROWSER_UI_WEB_APPLICATIONS_SHARE_TARGET_UTILS_H_
#define CHROME_BROWSER_UI_WEB_APPLICATIONS_SHARE_TARGET_UTILS_H_
#include <string>
#include <vector>
#include "chrome/browser/ui/browser_navigator_params.h"
#include "components/services/app_service/public/mojom/types.mojom.h"
class Browser;
namespace apps {
struct ShareTarget;
} // namespace apps
namespace web_app {
struct SharedField {
std::string name;
std::string value;
bool operator==(const SharedField& other) const;
bool operator!=(const SharedField& other) const { return !(*this == other); }
};
std::vector<SharedField> ExtractSharedFields(
const apps::ShareTarget& share_target,
const apps::mojom::Intent& intent);
NavigateParams NavigateParamsForShareTarget(
Browser* browser,
const apps::ShareTarget& share_target,
const apps::mojom::Intent& intent);
} // namespace web_app
#endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_SHARE_TARGET_UTILS_H_
// 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 "chrome/browser/ui/web_applications/share_target_utils.h"
#include "components/services/app_service/public/cpp/share_target.h"
#include "components/services/app_service/public/mojom/types.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace web_app {
TEST(ShareTargetUtils, ExtractTitle) {
apps::mojom::Intent intent;
intent.share_title = "Today's topic";
{
apps::ShareTarget share_target;
share_target.params.text = "body";
share_target.params.url = "link";
EXPECT_EQ(ExtractSharedFields(share_target, intent),
std::vector<SharedField>());
}
{
apps::ShareTarget share_target;
share_target.params.title = "subject";
std::vector<SharedField> expected = {{"subject", "Today's topic"}};
EXPECT_EQ(ExtractSharedFields(share_target, intent), expected);
}
}
TEST(ShareTargetUtils, ExtractText) {
apps::mojom::Intent intent;
intent.share_text = "Here's a long message.";
{
apps::ShareTarget share_target;
share_target.params.title = "subject";
share_target.params.url = "link";
EXPECT_EQ(ExtractSharedFields(share_target, intent),
std::vector<SharedField>());
}
{
apps::ShareTarget share_target;
share_target.params.text = "body";
std::vector<SharedField> expected = {{"body", "Here's a long message."}};
EXPECT_EQ(ExtractSharedFields(share_target, intent), expected);
}
}
TEST(ShareTargetUtils, ExtractUrl) {
apps::mojom::Intent intent;
// Shared URLs are serialized in share_text.
intent.share_text = "https://example.com/~me/index.html#part";
{
apps::ShareTarget share_target;
share_target.params.title = "subject";
share_target.params.text = "body";
EXPECT_EQ(ExtractSharedFields(share_target, intent),
std::vector<SharedField>());
}
{
apps::ShareTarget share_target;
share_target.params.url = "link";
std::vector<SharedField> expected = {
{"link", "https://example.com/~me/index.html#part"}};
EXPECT_EQ(ExtractSharedFields(share_target, intent), expected);
}
}
TEST(ShareTargetUtils, ExtractTitleTextUrl) {
apps::mojom::Intent intent;
intent.share_title = "Browse";
intent.share_text =
"Visit the sites https://example.com/ and https://example.org/";
{
apps::ShareTarget share_target;
share_target.params.title = "subject";
share_target.params.text = "body";
share_target.params.url = "link";
std::vector<SharedField> expected = {
{"subject", "Browse"},
{"body", "Visit the sites https://example.com/ and"},
{"link", "https://example.org/"}};
EXPECT_EQ(ExtractSharedFields(share_target, intent), expected);
}
{
apps::ShareTarget share_target;
share_target.params.title = "subject";
std::vector<SharedField> expected = {{"subject", "Browse"}};
EXPECT_EQ(ExtractSharedFields(share_target, intent), expected);
}
{
apps::ShareTarget share_target;
share_target.params.text = "body";
std::vector<SharedField> expected = {
{"body", "Visit the sites https://example.com/ and"}};
EXPECT_EQ(ExtractSharedFields(share_target, intent), expected);
}
{
apps::ShareTarget share_target;
share_target.params.url = "link";
std::vector<SharedField> expected = {{"link", "https://example.org/"}};
EXPECT_EQ(ExtractSharedFields(share_target, intent), expected);
}
}
} // namespace web_app
...@@ -6,17 +6,11 @@ ...@@ -6,17 +6,11 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_macros.h"
#include "base/ranges/algorithm.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h" #include "build/chromeos_buildflags.h"
#include "chrome/browser/app_mode/app_mode_utils.h" #include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/apps/app_service/app_launch_params.h"
...@@ -31,6 +25,7 @@ ...@@ -31,6 +25,7 @@
#include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/web_applications/share_target_utils.h"
#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h" #include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h" #include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
#include "chrome/browser/web_applications/components/app_registry_controller.h" #include "chrome/browser/web_applications/components/app_registry_controller.h"
...@@ -44,7 +39,6 @@ ...@@ -44,7 +39,6 @@
#include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_tab_helper.h" #include "chrome/browser/web_applications/web_app_tab_helper.h"
#include "chrome/browser/web_launch/web_launch_files_helper.h" #include "chrome/browser/web_launch/web_launch_files_helper.h"
#include "chrome/browser/web_share_target/target_util.h"
#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "content/public/browser/page_navigator.h" #include "content/public/browser/page_navigator.h"
...@@ -52,20 +46,12 @@ ...@@ -52,20 +46,12 @@
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/referrer.h" #include "content/public/common/referrer.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "net/base/mime_util.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_url.h"
#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/features.h"
#include "ui/base/page_transition_types.h" #include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h" #include "ui/base/window_open_disposition.h"
#include "ui/display/scoped_display_for_new_windows.h" #include "ui/display/scoped_display_for_new_windows.h"
#include "url/gurl.h" #include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
#endif
namespace web_app { namespace web_app {
namespace { namespace {
...@@ -100,79 +86,6 @@ content::WebContents* NavigateWebAppUsingParams(const std::string& app_id, ...@@ -100,79 +86,6 @@ content::WebContents* NavigateWebAppUsingParams(const std::string& app_id,
return web_contents; return web_contents;
} }
NavigateParams NavigateParamsForShareTarget(
Browser* browser,
const apps::ShareTarget& share_target,
const apps::mojom::Intent& intent) {
NavigateParams nav_params(browser, share_target.action,
ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
#if BUILDFLAG(IS_CHROMEOS_ASH)
std::vector<std::string> names;
std::vector<std::string> values;
std::vector<std::string> filenames;
std::vector<std::string> types;
std::vector<bool> is_value_file_uris;
DCHECK(intent.mime_type.has_value());
DCHECK(intent.file_urls.has_value());
const std::string& mime_type = intent.mime_type.value();
std::string name;
for (const apps::ShareTarget::Files& files : share_target.params.files) {
// Filter on MIME types. Chrome OS does not filter on file extensions.
// https://w3c.github.io/web-share-target/level-2/#dfn-accepted
if (base::ranges::any_of(files.accept, [&mime_type](const auto& criteria) {
return !base::StartsWith(criteria, ".") &&
net::MatchesMimeType(criteria, mime_type);
})) {
name = files.name;
break;
}
}
if (name.empty()) {
VLOG(1) << "Received unexpected MIME type: " << mime_type;
} else {
// Files for Web Share intents are created by the browser in
// a .WebShare directory, with generated file names and file urls - see
// //chrome/browser/webshare/chromeos/sharesheet_client.cc
for (const GURL& file_url : intent.file_urls.value()) {
storage::FileSystemContext* file_system_context =
file_manager::util::GetFileSystemContextForExtensionId(
browser->profile(), extension_misc::kFilesManagerAppId);
storage::FileSystemURL file_system_url =
file_system_context->CrackURL(file_url);
if (!file_system_url.is_valid()) {
VLOG(1) << "Received unexpected file URL: " << file_url.spec();
continue;
}
names.push_back(name);
values.push_back(file_system_url.path().AsUTF8Unsafe());
filenames.push_back(file_system_url.path().BaseName().AsUTF8Unsafe());
types.push_back(mime_type);
is_value_file_uris.push_back(true);
}
}
const std::string boundary = net::GenerateMimeMultipartBoundary();
const std::string header_list = base::StringPrintf(
"Content-Type: multipart/form-data; boundary=%s\r\n", boundary.c_str());
scoped_refptr<network::ResourceRequestBody> post_data =
web_share_target::ComputeMultipartBody(names, values, is_value_file_uris,
filenames, types, boundary);
nav_params.post_data = post_data;
nav_params.extra_headers = header_list;
#else
// TODO(crbug.com/1153194): Support Web Share Target on Windows.
// TODO(crbug.com/1153195): Support Web Share Target on Mac.
NOTIMPLEMENTED();
#endif
return nav_params;
}
GURL GetLaunchUrl(WebAppProvider& provider, GURL GetLaunchUrl(WebAppProvider& provider,
const apps::AppLaunchParams& params, const apps::AppLaunchParams& params,
const apps::ShareTarget* share_target) { const apps::ShareTarget* share_target) {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/files/file.h" #include "base/files/file.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
...@@ -62,6 +63,13 @@ base::FilePath StoreSharedFile(const base::FilePath& directory, ...@@ -62,6 +63,13 @@ base::FilePath StoreSharedFile(const base::FilePath& directory,
return path; return path;
} }
content::EvalJsResult ReadTextContent(content::WebContents* web_contents,
const char* id) {
const std::string script =
base::StringPrintf("document.getElementById('%s').textContent", id);
return content::EvalJs(web_contents, script);
}
} // namespace } // namespace
namespace web_app { namespace web_app {
...@@ -96,7 +104,7 @@ class WebShareTargetBrowserTest : public WebAppControllerBrowserTest { ...@@ -96,7 +104,7 @@ class WebShareTargetBrowserTest : public WebAppControllerBrowserTest {
} }
}; };
IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareText) { IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareTextFiles) {
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url()); const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url());
const base::FilePath directory = PrepareWebShareDirectory(profile()); const base::FilePath directory = PrepareWebShareDirectory(profile());
...@@ -114,16 +122,14 @@ IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareText) { ...@@ -114,16 +122,14 @@ IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareText) {
profile(), std::move(file_paths), std::move(content_types)); profile(), std::move(file_paths), std::move(content_types));
} }
const std::string script = "document.getElementById('records').textContent";
content::WebContents* const web_contents = content::WebContents* const web_contents =
LaunchAppWithIntent(app_id, std::move(intent)); LaunchAppWithIntent(app_id, std::move(intent));
const content::EvalJsResult result = content::EvalJs(web_contents, script); EXPECT_EQ("1,2,3,4,5 6,7,8,9,0", ReadTextContent(web_contents, "records"));
EXPECT_EQ("1,2,3,4,5 6,7,8,9,0", result);
RemoveWebShareDirectory(directory); RemoveWebShareDirectory(directory);
} }
IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareImage) { IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareImageWithText) {
ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(embedded_test_server()->Start());
const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url()); const AppId app_id = web_app::InstallWebAppFromManifest(browser(), app_url());
const base::FilePath directory = PrepareWebShareDirectory(profile()); const base::FilePath directory = PrepareWebShareDirectory(profile());
...@@ -136,14 +142,18 @@ IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareImage) { ...@@ -136,14 +142,18 @@ IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareImage) {
std::vector<base::FilePath> file_paths({first_svg}); std::vector<base::FilePath> file_paths({first_svg});
std::vector<std::string> content_types(1, "image/svg+xml"); std::vector<std::string> content_types(1, "image/svg+xml");
intent = apps_util::CreateShareIntentFromFiles( intent = apps_util::CreateShareIntentFromFiles(
profile(), std::move(file_paths), std::move(content_types)); profile(), std::move(file_paths), std::move(content_types),
/*share_text=*/"Euclid https://example.org/",
/*share_title=*/"Elements");
} }
const std::string script = "document.getElementById('graphs').textContent";
content::WebContents* const web_contents = content::WebContents* const web_contents =
LaunchAppWithIntent(app_id, std::move(intent)); LaunchAppWithIntent(app_id, std::move(intent));
const content::EvalJsResult result = content::EvalJs(web_contents, script); EXPECT_EQ("picture", ReadTextContent(web_contents, "graphs"));
EXPECT_EQ("picture", result);
EXPECT_EQ("Elements", ReadTextContent(web_contents, "headline"));
EXPECT_EQ("Euclid", ReadTextContent(web_contents, "author"));
EXPECT_EQ("https://example.org/", ReadTextContent(web_contents, "link"));
RemoveWebShareDirectory(directory); RemoveWebShareDirectory(directory);
} }
...@@ -169,11 +179,9 @@ IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareAudio) { ...@@ -169,11 +179,9 @@ IN_PROC_BROWSER_TEST_F(WebShareTargetBrowserTest, ShareAudio) {
profile(), std::move(file_paths), std::move(content_types)); profile(), std::move(file_paths), std::move(content_types));
} }
const std::string script = "document.getElementById('notes').textContent";
content::WebContents* const web_contents = content::WebContents* const web_contents =
LaunchAppWithIntent(app_id, std::move(intent)); LaunchAppWithIntent(app_id, std::move(intent));
const content::EvalJsResult result = content::EvalJs(web_contents, script); EXPECT_EQ("a b c", ReadTextContent(web_contents, "notes"));
EXPECT_EQ("a b c", result);
RemoveWebShareDirectory(directory); RemoveWebShareDirectory(directory);
} }
......
...@@ -4658,6 +4658,7 @@ test("unit_tests") { ...@@ -4658,6 +4658,7 @@ test("unit_tests") {
"../browser/ui/user_education/reopen_tab_in_product_help_trigger_unittest.cc", "../browser/ui/user_education/reopen_tab_in_product_help_trigger_unittest.cc",
"../browser/ui/user_education/reopen_tab_in_product_help_unittest.cc", "../browser/ui/user_education/reopen_tab_in_product_help_unittest.cc",
"../browser/ui/web_applications/app_browser_controller_unittest.cc", "../browser/ui/web_applications/app_browser_controller_unittest.cc",
"../browser/ui/web_applications/share_target_utils_unittest.cc",
"../browser/ui/web_applications/web_app_launch_utils_unittest.cc", "../browser/ui/web_applications/web_app_launch_utils_unittest.cc",
"../browser/ui/webui/components/components_handler_unittest.cc", "../browser/ui/webui/components/components_handler_unittest.cc",
"../browser/ui/webui/customize_themes/chrome_customize_themes_handler_unittest.cc", "../browser/ui/webui/customize_themes/chrome_customize_themes_handler_unittest.cc",
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
"method": "POST", "method": "POST",
"enctype": "multipart/form-data", "enctype": "multipart/form-data",
"params": { "params": {
"title": "headline",
"text": "author",
"url": "link",
"files": [ "files": [
{ {
"name": "records", "name": "records",
......
...@@ -18,6 +18,10 @@ function respondToShare(event) { ...@@ -18,6 +18,10 @@ function respondToShare(event) {
let body = await template.text(); let body = await template.text();
const formData = await event.request.formData(); const formData = await event.request.formData();
body = body.replace('{{headline}}', formData.get('headline'))
.replace('{{author}}', formData.get('author'))
.replace('{{link}}', formData.get('link'));
const init = { const init = {
status: 200, status: 200,
statusText: 'OK', statusText: 'OK',
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
<link rel="icon" href="basic-48.png"> <link rel="icon" href="basic-48.png">
</head> </head>
<body> <body>
<section id="headline">{{headline}}</section>
<section id="author">{{author}}</section>
<section id="link">{{link}}</section>
<section id="records">{{records}}</section> <section id="records">{{records}}</section>
<section id="graphs">{{graphs}}</section> <section id="graphs">{{graphs}}</section>
<section id="notes">{{notes}}</section> <section id="notes">{{notes}}</section>
......
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