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 @@ ...@@ -8,6 +8,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include "chrome/browser/sharesheet/sharesheet_service_factory.h" #include "chrome/browser/sharesheet/sharesheet_service_factory.h"
#include "chrome/browser/webshare/chromeos/prepare_directory_task.h" #include "chrome/browser/webshare/chromeos/prepare_directory_task.h"
#include "chrome/browser/webshare/chromeos/store_files_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 "components/services/app_service/public/cpp/intent_util.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -48,6 +50,16 @@ base::FilePath GenerateFileName(const base::FilePath& directory, ...@@ -48,6 +50,16 @@ base::FilePath GenerateFileName(const base::FilePath& directory,
return directory.Append(filename); 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
namespace webshare { namespace webshare {
...@@ -145,19 +157,28 @@ void SharesheetClient::OnStoreFiles(blink::mojom::ShareError error) { ...@@ -145,19 +157,28 @@ void SharesheetClient::OnStoreFiles(blink::mojom::ShareError error) {
return; return;
} }
blink::mojom::ShareError result = GetSharesheetCallback().Run( GetSharesheetCallback().Run(
web_contents(), std::move(current_share_->file_urls), 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; current_share_ = base::nullopt;
} }
// static // static
blink::mojom::ShareError SharesheetClient::ShowSharesheet( void SharesheetClient::ShowSharesheet(content::WebContents* web_contents,
content::WebContents* web_contents, std::vector<GURL> file_urls,
std::vector<GURL> file_urls, std::vector<std::string> content_types,
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* const profile =
Profile::FromBrowserContext(web_contents->GetBrowserContext()); Profile::FromBrowserContext(web_contents->GetBrowserContext());
DCHECK(profile); DCHECK(profile);
...@@ -169,9 +190,7 @@ blink::mojom::ShareError SharesheetClient::ShowSharesheet( ...@@ -169,9 +190,7 @@ blink::mojom::ShareError SharesheetClient::ShowSharesheet(
web_contents, web_contents,
apps_util::CreateShareIntentFromFiles(std::move(file_urls), apps_util::CreateShareIntentFromFiles(std::move(file_urls),
std::move(content_types)), std::move(content_types)),
base::NullCallback()); std::move(close_callback));
return blink::mojom::ShareError::OK;
} }
SharesheetClient::SharesheetCallback& SharesheetClient::SharesheetCallback&
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h" #include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -26,10 +27,12 @@ class PrepareDirectoryTask; ...@@ -26,10 +27,12 @@ class PrepareDirectoryTask;
// sharesheet::SharesheetService. // sharesheet::SharesheetService.
class SharesheetClient : public content::WebContentsObserver { class SharesheetClient : public content::WebContentsObserver {
public: public:
using SharesheetCallback = base::RepeatingCallback<blink::mojom::ShareError( using CloseCallback = sharesheet::CloseCallback;
content::WebContents* web_contents, using SharesheetCallback =
std::vector<GURL> file_urls, base::RepeatingCallback<void(content::WebContents* web_contents,
std::vector<std::string> content_types)>; std::vector<GURL> file_urls,
std::vector<std::string> content_types,
CloseCallback close_callback)>;
explicit SharesheetClient(content::WebContents* web_contents); explicit SharesheetClient(content::WebContents* web_contents);
SharesheetClient(const SharesheetClient&) = delete; SharesheetClient(const SharesheetClient&) = delete;
...@@ -49,10 +52,12 @@ class SharesheetClient : public content::WebContentsObserver { ...@@ -49,10 +52,12 @@ class SharesheetClient : public content::WebContentsObserver {
void OnStoreFiles(blink::mojom::ShareError); void OnStoreFiles(blink::mojom::ShareError);
static blink::mojom::ShareError ShowSharesheet( void OnShowSharesheet(sharesheet::SharesheetResult result);
content::WebContents* web_contents,
std::vector<GURL> file_urls, static void ShowSharesheet(content::WebContents* web_contents,
std::vector<std::string> content_types); std::vector<GURL> file_urls,
std::vector<std::string> content_types,
CloseCallback close_callback);
static SharesheetCallback& GetSharesheetCallback(); static SharesheetCallback& GetSharesheetCallback();
......
...@@ -74,7 +74,8 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, ShareTwoFiles) { ...@@ -74,7 +74,8 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, ShareTwoFiles) {
SharesheetClient::SetSharesheetCallbackForTesting(base::BindLambdaForTesting( SharesheetClient::SetSharesheetCallbackForTesting(base::BindLambdaForTesting(
[contents, &first_file_path, &second_file_path]( [contents, &first_file_path, &second_file_path](
content::WebContents* web_contents, std::vector<GURL> file_urls, 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(contents, web_contents);
EXPECT_EQ(file_urls.size(), 2U); EXPECT_EQ(file_urls.size(), 2U);
...@@ -85,7 +86,7 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, ShareTwoFiles) { ...@@ -85,7 +86,7 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, ShareTwoFiles) {
EXPECT_EQ(content_types[0], "audio/mp3"); EXPECT_EQ(content_types[0], "audio/mp3");
EXPECT_EQ(content_types[1], "video/mp4"); 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)); EXPECT_EQ("share succeeded", content::EvalJs(contents, script));
...@@ -106,9 +107,10 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) { ...@@ -106,9 +107,10 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) {
SharesheetClient::SetSharesheetCallbackForTesting( SharesheetClient::SetSharesheetCallbackForTesting(
base::BindLambdaForTesting( base::BindLambdaForTesting(
[contents, &file_path](content::WebContents* web_contents, [contents, &file_path](
std::vector<GURL> file_urls, 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(contents, web_contents);
EXPECT_EQ(file_urls.size(), 1U); EXPECT_EQ(file_urls.size(), 1U);
...@@ -117,7 +119,8 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) { ...@@ -117,7 +119,8 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) {
EXPECT_EQ(content_types.size(), 1U); EXPECT_EQ(content_types.size(), 1U);
EXPECT_EQ(content_types[0], "image/webp"); 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)); EXPECT_EQ("share succeeded", content::EvalJs(contents, script));
...@@ -125,4 +128,22 @@ IN_PROC_BROWSER_TEST_F(SharesheetClientBrowserTest, RepeatedShare) { ...@@ -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 } // namespace webshare
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
using blink::mojom::ShareError; using blink::mojom::ShareError;
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "chrome/browser/sharesheet/sharesheet_types.h"
#include "chrome/browser/webshare/chromeos/sharesheet_client.h" #include "chrome/browser/webshare/chromeos/sharesheet_client.h"
#endif #endif
...@@ -114,10 +115,11 @@ class ShareServiceUnitTest : public ChromeRenderViewHostTestHarness { ...@@ -114,10 +115,11 @@ class ShareServiceUnitTest : public ChromeRenderViewHostTestHarness {
} }
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
static ShareError AcceptShareRequest(content::WebContents* web_contents, static void AcceptShareRequest(content::WebContents* web_contents,
std::vector<GURL> file_urls, std::vector<GURL> file_urls,
std::vector<std::string> content_types) { std::vector<std::string> content_types,
return ShareError::OK; sharesheet::CloseCallback close_callback) {
std::move(close_callback).Run(sharesheet::SharesheetResult::kSuccess);
} }
#endif #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