0

Web Share: Support sharing title/text/url without files on ChromeOS

Web apps on Chrome OS may use the Web Share API to send title,
text and/or url, even when files are not also being shared at
the same time.

Support for sharing title/text/url in combination with files is
already implemented:
https://chromium-review.googlesource.com/c/chromium/src/+/2569329


Bug: 1127670
Change-Id: Iae5d51f0012d7134309af80ba377ecd60f311efd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2576296
Commit-Queue: Eric Willigers <ericwilligers@chromium.org>
Reviewed-by: Alan Cutter <alancutter@chromium.org>
Auto-Submit: Eric Willigers <ericwilligers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834151}
This commit is contained in:
Eric Willigers
2020-12-07 09:41:39 +00:00
committed by Chromium LUCI CQ
parent 580c10dd72
commit f17737a24f
4 changed files with 115 additions and 27 deletions

@@ -91,12 +91,6 @@ void SharesheetClient::Share(
return;
}
if (files.empty()) {
// TODO(crbug.com/1127670): Support title/text/url sharing without files.
std::move(callback).Run(blink::mojom::ShareError::CANCELED);
return;
}
Profile* const profile =
Profile::FromBrowserContext(web_contents()->GetBrowserContext());
DCHECK(profile);
@@ -117,6 +111,16 @@ void SharesheetClient::Share(
current_share_->title = title;
current_share_->callback = std::move(callback);
if (current_share_->files.empty()) {
GetSharesheetCallback().Run(
web_contents(), current_share_->file_paths,
current_share_->content_types, current_share_->text,
current_share_->title,
base::BindOnce(&SharesheetClient::OnShowSharesheet,
weak_ptr_factory_.GetWeakPtr()));
return;
}
current_share_->prepare_directory_task =
std::make_unique<PrepareDirectoryTask>(
current_share_->directory, kMaxSharedFileBytes,
@@ -167,9 +171,8 @@ void SharesheetClient::OnStoreFiles(blink::mojom::ShareError error) {
}
GetSharesheetCallback().Run(
web_contents(), std::move(current_share_->file_paths),
std::move(current_share_->content_types), current_share_->text,
current_share_->title,
web_contents(), current_share_->file_paths, current_share_->content_types,
current_share_->text, current_share_->title,
base::BindOnce(&SharesheetClient::OnShowSharesheet,
weak_ptr_factory_.GetWeakPtr()));
}

@@ -59,12 +59,14 @@ class SharesheetClientBrowserTest : public InProcessBrowserTest {
return embedded_test_server()->GetURL("/webshare/index.html");
}
void ConfirmShareText(const std::string& script,
const char* expected_text,
const char* expected_title) {
void ConfirmShareText(
const std::string& script,
const char* expected_text,
const char* expected_title,
const std::vector<std::string>& expected_content_types) {
SharesheetClient::SetSharesheetCallbackForTesting(
base::BindLambdaForTesting(
[&expected_text, &expected_title](
[&expected_text, &expected_title, &expected_content_types](
content::WebContents* in_contents,
const std::vector<base::FilePath>& file_paths,
const std::vector<std::string>& content_types,
@@ -72,14 +74,15 @@ class SharesheetClientBrowserTest : public InProcessBrowserTest {
SharesheetClient::CloseCallback close_callback) {
EXPECT_EQ(text, expected_text);
EXPECT_EQ(title, expected_title);
EXPECT_EQ(file_paths.size(), content_types.size());
EXPECT_EQ(content_types, expected_content_types);
std::move(close_callback)
.Run(sharesheet::SharesheetResult::kCancel);
.Run(sharesheet::SharesheetResult::kSuccess);
}));
content::WebContents* const contents =
browser()->tab_strip_model()->GetActiveWebContents();
EXPECT_EQ("share failed: AbortError: Share canceled",
content::EvalJs(contents, script));
EXPECT_EQ("share succeeded", content::EvalJs(contents, script));
}
private:
@@ -179,24 +182,45 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, CancelledShare) {
content::EvalJs(contents, script));
}
IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, Text) {
ASSERT_TRUE(embedded_test_server()->Start());
ui_test_utils::NavigateToURL(browser(), GetAppUrl());
ConfirmShareText("share_title()",
/*expected_text=*/"",
/*expected_title=*/"Subject", /*expected_content_types=*/{});
ConfirmShareText("share_title_url()",
/*expected_text=*/"https://example.com/",
/*expected_title=*/"Subject", /*expected_content_types=*/{});
ConfirmShareText("share_text()",
/*expected_text=*/"Message",
/*expected_title=*/"", /*expected_content_types=*/{});
ConfirmShareText("share_text_url()",
/*expected_text=*/"Message https://example.com/",
/*expected_title=*/"", /*expected_content_types=*/{});
ConfirmShareText("share_url()",
/*expected_text=*/"https://example.com/",
/*expected_title=*/"", /*expected_content_types=*/{});
}
IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, TextWithFile) {
ASSERT_TRUE(embedded_test_server()->Start());
ui_test_utils::NavigateToURL(browser(), GetAppUrl());
const std::vector<std::string> expected_content_types{"image/webp"};
ConfirmShareText("share_file_title()",
/*expected_text=*/"",
/*expected_title=*/"Subject");
/*expected_title=*/"Subject", expected_content_types);
ConfirmShareText("share_file_title_url()",
/*expected_text=*/"https://example.com/",
/*expected_title=*/"Subject");
/*expected_title=*/"Subject", expected_content_types);
ConfirmShareText("share_file_text()",
/*expected_text=*/"Message",
/*expected_title=*/"");
/*expected_title=*/"", expected_content_types);
ConfirmShareText("share_file_text_url()",
/*expected_text=*/"Message https://example.com/",
/*expected_title=*/"");
/*expected_title=*/"", expected_content_types);
ConfirmShareText("share_file_url()",
/*expected_text=*/"https://example.com/",
/*expected_title=*/"");
/*expected_title=*/"", expected_content_types);
}
} // namespace webshare

@@ -13,6 +13,10 @@
#include "content/public/test/browser_test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "chrome/browser/webshare/chromeos/sharesheet_client.h"
#endif
#if defined(OS_WIN)
#include "chrome/browser/webshare/win/scoped_share_operation_fake_components.h"
#endif
@@ -23,13 +27,28 @@ class ShareServiceBrowserTest : public InProcessBrowserTest {
feature_list_.InitAndEnableFeature(features::kWebShare);
}
#if defined(OS_WIN)
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
#if defined(OS_CHROMEOS)
webshare::SharesheetClient::SetSharesheetCallbackForTesting(
base::BindRepeating(&ShareServiceBrowserTest::AcceptShareRequest));
#endif
#if defined(OS_WIN)
if (!IsSupportedEnvironment())
return;
ASSERT_NO_FATAL_FAILURE(scoped_fake_components_.SetUp());
#endif
}
#if defined(OS_CHROMEOS)
static void AcceptShareRequest(content::WebContents* web_contents,
const std::vector<base::FilePath>& file_paths,
const std::vector<std::string>& content_types,
const std::string& text,
const std::string& title,
sharesheet::CloseCallback close_callback) {
std::move(close_callback).Run(sharesheet::SharesheetResult::kSuccess);
}
#endif
@@ -63,10 +82,5 @@ IN_PROC_BROWSER_TEST_F(ShareServiceBrowserTest, Text) {
const std::string script = "share_text('hello')";
const content::EvalJsResult result = content::EvalJs(contents, script);
#if defined(OS_CHROMEOS)
// ChromeOS currently only supports file sharing.
EXPECT_EQ("share failed: AbortError: Share canceled", result);
#else
EXPECT_EQ("share succeeded", result);
#endif
}

@@ -41,6 +41,53 @@
}
}
async function share_title() {
try {
await navigator.share({title: "Subject"});
return 'share succeeded';
} catch(error) {
return ('share failed: ' + error);
}
}
async function share_title_url() {
try {
await navigator.share({title: "Subject",
url: "https://example.com/"});
return 'share succeeded';
} catch(error) {
return ('share failed: ' + error);
}
}
async function share_text() {
try {
await navigator.share({text: "Message"});
return 'share succeeded';
} catch(error) {
return ('share failed: ' + error);
}
}
async function share_text_url() {
try {
await navigator.share({text: "Message",
url: "https://example.com/"});
return 'share succeeded';
} catch(error) {
return ('share failed: ' + error);
}
}
async function share_url() {
try {
await navigator.share({url: "https://example.com/"});
return 'share succeeded';
} catch(error) {
return ('share failed: ' + error);
}
}
async function share_file_title() {
try {
const single_file = create_file('sample.webp', 'image/webp', 12);