Commit e3644298 authored by Eric Willigers's avatar Eric Willigers Committed by Commit Bot

Web Share: Wait for ChromeOS sharesheet to complete

The promise returned by navigator.share() resolves if the share
completes successfully, and rejects if the share is cancelled or
otherwise unsuccessful.

Spec:
https://w3c.github.io/web-share/#share-method

Builds on
https://chromium-review.googlesource.com/c/chromium/src/+/2434078


Bug: 1126788
Change-Id: Ia2ae218bd9b6640bdac21fb84ed12956b17cdb0a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2437552
Commit-Queue: Eric Willigers <ericwilligers@chromium.org>
Reviewed-by: default avatarMelissa Zhang <melzhang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#812486}
parent 75bad9b8
......@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
......@@ -16,6 +17,7 @@
#include "chrome/browser/sharesheet/sharesheet_service_factory.h"
#include "chrome/browser/webshare/chromeos/prepare_directory_task.h"
#include "chrome/browser/webshare/chromeos/store_files_task.h"
#include "chrome/common/chrome_features.h"
#include "components/services/app_service/public/cpp/intent_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
......@@ -48,6 +50,16 @@ base::FilePath GenerateFileName(const base::FilePath& directory,
return directory.Append(filename);
}
blink::mojom::ShareError SharesheetResultToShareError(
sharesheet::SharesheetResult result) {
switch (result) {
case sharesheet::SharesheetResult::kSuccess:
return blink::mojom::ShareError::OK;
case sharesheet::SharesheetResult::kCancel:
return blink::mojom::ShareError::CANCELED;
}
}
} // namespace
namespace webshare {
......@@ -145,19 +157,28 @@ void SharesheetClient::OnStoreFiles(blink::mojom::ShareError error) {
return;
}
blink::mojom::ShareError result = GetSharesheetCallback().Run(
GetSharesheetCallback().Run(
web_contents(), std::move(current_share_->file_urls),
std::move(current_share_->content_types));
std::move(current_share_->content_types),
base::BindOnce(&SharesheetClient::OnShowSharesheet,
weak_ptr_factory_.GetWeakPtr()));
}
std::move(current_share_->callback).Run(result);
void SharesheetClient::OnShowSharesheet(sharesheet::SharesheetResult result) {
std::move(current_share_->callback).Run(SharesheetResultToShareError(result));
current_share_ = base::nullopt;
}
// static
blink::mojom::ShareError SharesheetClient::ShowSharesheet(
content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types) {
void SharesheetClient::ShowSharesheet(content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types,
CloseCallback close_callback) {
if (!base::FeatureList::IsEnabled(features::kSharesheet)) {
std::move(close_callback).Run(sharesheet::SharesheetResult::kCancel);
return;
}
Profile* const profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext());
DCHECK(profile);
......@@ -169,9 +190,7 @@ blink::mojom::ShareError SharesheetClient::ShowSharesheet(
web_contents,
apps_util::CreateShareIntentFromFiles(std::move(file_urls),
std::move(content_types)),
base::NullCallback());
return blink::mojom::ShareError::OK;
std::move(close_callback));
}
SharesheetClient::SharesheetCallback&
......
......@@ -10,6 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "content/public/browser/web_contents_observer.h"
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
#include "url/gurl.h"
......@@ -26,10 +27,12 @@ class PrepareDirectoryTask;
// sharesheet::SharesheetService.
class SharesheetClient : public content::WebContentsObserver {
public:
using SharesheetCallback = base::RepeatingCallback<blink::mojom::ShareError(
content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types)>;
using CloseCallback = sharesheet::CloseCallback;
using SharesheetCallback =
base::RepeatingCallback<void(content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types,
CloseCallback close_callback)>;
explicit SharesheetClient(content::WebContents* web_contents);
SharesheetClient(const SharesheetClient&) = delete;
......@@ -49,10 +52,12 @@ class SharesheetClient : public content::WebContentsObserver {
void OnStoreFiles(blink::mojom::ShareError);
static blink::mojom::ShareError ShowSharesheet(
content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types);
void OnShowSharesheet(sharesheet::SharesheetResult result);
static void ShowSharesheet(content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types,
CloseCallback close_callback);
static SharesheetCallback& GetSharesheetCallback();
......
......@@ -74,7 +74,8 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, ShareTwoFiles) {
SharesheetClient::SetSharesheetCallbackForTesting(base::BindLambdaForTesting(
[contents, &first_file_path, &second_file_path](
content::WebContents* web_contents, std::vector<GURL> file_urls,
std::vector<std::string> content_types) {
std::vector<std::string> content_types,
SharesheetClient::CloseCallback close_callback) {
EXPECT_EQ(contents, web_contents);
EXPECT_EQ(file_urls.size(), 2U);
......@@ -85,7 +86,7 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, ShareTwoFiles) {
EXPECT_EQ(content_types[0], "audio/mp3");
EXPECT_EQ(content_types[1], "video/mp4");
return blink::mojom::ShareError::OK;
std::move(close_callback).Run(sharesheet::SharesheetResult::kSuccess);
}));
EXPECT_EQ("share succeeded", content::EvalJs(contents, script));
......@@ -106,9 +107,10 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) {
SharesheetClient::SetSharesheetCallbackForTesting(
base::BindLambdaForTesting(
[contents, &file_path](content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types) {
[contents, &file_path](
content::WebContents* web_contents, std::vector<GURL> file_urls,
std::vector<std::string> content_types,
SharesheetClient::CloseCallback close_callback) {
EXPECT_EQ(contents, web_contents);
EXPECT_EQ(file_urls.size(), 1U);
......@@ -117,7 +119,8 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) {
EXPECT_EQ(content_types.size(), 1U);
EXPECT_EQ(content_types[0], "image/webp");
return blink::mojom::ShareError::OK;
std::move(close_callback)
.Run(sharesheet::SharesheetResult::kSuccess);
}));
EXPECT_EQ("share succeeded", content::EvalJs(contents, script));
......@@ -125,4 +128,22 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) {
}
}
IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, CancelledShare) {
const std::string script = "share_single_file()";
ASSERT_TRUE(embedded_test_server()->Start());
content::WebContents* const contents =
browser()->tab_strip_model()->GetActiveWebContents();
ui_test_utils::NavigateToURL(browser(), GetAppUrl());
SharesheetClient::SetSharesheetCallbackForTesting(base::BindLambdaForTesting(
[](content::WebContents* web_contents, std::vector<GURL> file_urls,
std::vector<std::string> content_types,
SharesheetClient::CloseCallback close_callback) {
std::move(close_callback).Run(sharesheet::SharesheetResult::kCancel);
}));
EXPECT_EQ("share failed: AbortError: Share canceled",
content::EvalJs(contents, script));
}
} // namespace webshare
......@@ -26,6 +26,7 @@
using blink::mojom::ShareError;
#if defined(OS_CHROMEOS)
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "chrome/browser/webshare/chromeos/sharesheet_client.h"
#endif
......@@ -114,10 +115,11 @@ class ShareServiceUnitTest : public ChromeRenderViewHostTestHarness {
}
#if defined(OS_CHROMEOS)
static ShareError AcceptShareRequest(content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types) {
return ShareError::OK;
static void AcceptShareRequest(content::WebContents* web_contents,
std::vector<GURL> file_urls,
std::vector<std::string> content_types,
sharesheet::CloseCallback close_callback) {
std::move(close_callback).Run(sharesheet::SharesheetResult::kSuccess);
}
#endif
......
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