Reland "WebShare: Implement SharingServicePicker"
This is a reland of 07700ae66e
Original change's description:
> WebShare: Implement SharingServicePicker
>
> This CL completes the implementation of webshare on mac.
> The UX review is being tracked here: crbug.com/1162971
>
> To test manually:
> -launch chromium with flag 'WebShare'
> -go to https://w3c.github.io/web-share/demos/share-files.html
> -optionally, add a file to the form
> -click on Share
> -the NSSharingServicePicker should popup in the top-middle,
> overlapping the client and non-client area
>
> Bug: 1144920
> Change-Id: Ia28ad87fac82a9704c07122b57a144ce5aa5086e
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2668974
> Reviewed-by: Avi Drissman <avi@chromium.org>
> Reviewed-by: Daniel Murphy <dmurph@chromium.org>
> Reviewed-by: Eric Willigers <ericwilligers@chromium.org>
> Reviewed-by: Leonard Grey <lgrey@chromium.org>
> Reviewed-by: Dominick Ng <dominickn@chromium.org>
> Commit-Queue: Eric Willigers <ericwilligers@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#859624}
Bug: 1144920
Change-Id: Ied9df60b65fc19c366f9c0e038028563df976a5c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2737234
Reviewed-by: Avi Drissman <avi@chromium.org>
Reviewed-by: Dominick Ng <dominickn@chromium.org>
Reviewed-by: Eric Willigers <ericwilligers@chromium.org>
Reviewed-by: Leonard Grey <lgrey@chromium.org>
Reviewed-by: Daniel Murphy <dmurph@chromium.org>
Commit-Queue: Hassan Talat <hatalat@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#866720}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
69400eb99d
commit
e7f474a35e
chrome
browser
webshare
test
content
app_shim_remote_cocoa
DEPSrender_widget_host_ns_view_bridge.hrender_widget_host_ns_view_bridge.mmsharing_service_picker.hsharing_service_picker.mm
browser
BUILD.gn
renderer_host
common
public
browser
test
@ -33,6 +33,7 @@ class SharingServiceOperation final : content::WebContentsObserver {
|
|||||||
const std::vector<base::FilePath>& file_paths,
|
const std::vector<base::FilePath>& file_paths,
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const std::string& title,
|
const std::string& title,
|
||||||
|
const GURL& url,
|
||||||
blink::mojom::ShareService::ShareCallback close_callback)>;
|
blink::mojom::ShareService::ShareCallback close_callback)>;
|
||||||
|
|
||||||
SharingServiceOperation(const std::string& title,
|
SharingServiceOperation(const std::string& title,
|
||||||
@ -59,6 +60,7 @@ class SharingServiceOperation final : content::WebContentsObserver {
|
|||||||
const std::vector<base::FilePath>& file_paths,
|
const std::vector<base::FilePath>& file_paths,
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const std::string& title,
|
const std::string& title,
|
||||||
|
const GURL& url,
|
||||||
blink::mojom::ShareService::ShareCallback close_callback);
|
blink::mojom::ShareService::ShareCallback close_callback);
|
||||||
static SharePickerCallback& GetSharePickerCallback();
|
static SharePickerCallback& GetSharePickerCallback();
|
||||||
|
|
||||||
|
@ -6,16 +6,20 @@
|
|||||||
|
|
||||||
#include <AppKit/AppKit.h>
|
#include <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
#include "base/guid.h"
|
#include "base/guid.h"
|
||||||
#include "base/i18n/file_util_icu.h"
|
#include "base/i18n/file_util_icu.h"
|
||||||
#include "base/mac/scoped_nsobject.h"
|
#include "base/mac/scoped_nsobject.h"
|
||||||
|
#include "base/strings/string_util.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "chrome/browser/webshare/prepare_directory_task.h"
|
#include "chrome/browser/webshare/prepare_directory_task.h"
|
||||||
#include "chrome/browser/webshare/prepare_subdirectory_task.h"
|
#include "chrome/browser/webshare/prepare_subdirectory_task.h"
|
||||||
#include "chrome/browser/webshare/share_service_impl.h"
|
#include "chrome/browser/webshare/share_service_impl.h"
|
||||||
#include "chrome/browser/webshare/store_files_task.h"
|
#include "chrome/browser/webshare/store_files_task.h"
|
||||||
#include "content/public/browser/browser_context.h"
|
#include "content/public/browser/browser_context.h"
|
||||||
|
#include "content/public/browser/render_widget_host_view.h"
|
||||||
#include "content/public/browser/storage_partition.h"
|
#include "content/public/browser/storage_partition.h"
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "net/base/filename_util.h"
|
#include "net/base/filename_util.h"
|
||||||
@ -60,7 +64,7 @@ void SharingServiceOperation::Share(
|
|||||||
|
|
||||||
if (shared_files_.size() == 0) {
|
if (shared_files_.size() == 0) {
|
||||||
GetSharePickerCallback().Run(
|
GetSharePickerCallback().Run(
|
||||||
web_contents(), file_paths_, text_, title_,
|
web_contents(), file_paths_, text_, title_, url_,
|
||||||
base::BindOnce(&SharingServiceOperation::OnShowSharePicker,
|
base::BindOnce(&SharingServiceOperation::OnShowSharePicker,
|
||||||
weak_factory_.GetWeakPtr()));
|
weak_factory_.GetWeakPtr()));
|
||||||
return;
|
return;
|
||||||
@ -94,6 +98,8 @@ void SharingServiceOperation::OnPrepareDirectory(
|
|||||||
|
|
||||||
for (const auto& file : shared_files_) {
|
for (const auto& file : shared_files_) {
|
||||||
std::string file_name = file->name;
|
std::string file_name = file->name;
|
||||||
|
// Protecting against including paths in a file name.
|
||||||
|
base::ReplaceSubstringsAfterOffset(&file_name, 0, "/", "_");
|
||||||
base::i18n::ReplaceIllegalCharactersInPath(&file_name, '_');
|
base::i18n::ReplaceIllegalCharactersInPath(&file_name, '_');
|
||||||
file_paths_.push_back(
|
file_paths_.push_back(
|
||||||
GenerateUniqueSubDirectory(directory_).Append(file_name));
|
GenerateUniqueSubDirectory(directory_).Append(file_name));
|
||||||
@ -125,18 +131,24 @@ void SharingServiceOperation::OnPrepareSubDirectory(
|
|||||||
|
|
||||||
void SharingServiceOperation::OnStoreFiles(blink::mojom::ShareError error) {
|
void SharingServiceOperation::OnStoreFiles(blink::mojom::ShareError error) {
|
||||||
if (!web_contents() || error != blink::mojom::ShareError::OK) {
|
if (!web_contents() || error != blink::mojom::ShareError::OK) {
|
||||||
|
PrepareDirectoryTask::ScheduleSharedFileDeletion(
|
||||||
|
std::move(file_paths_), base::TimeDelta::FromMinutes(0));
|
||||||
std::move(callback_).Run(error);
|
std::move(callback_).Run(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetSharePickerCallback().Run(
|
GetSharePickerCallback().Run(
|
||||||
web_contents(), file_paths_, text_, title_,
|
web_contents(), file_paths_, text_, title_, url_,
|
||||||
base::BindOnce(&SharingServiceOperation::OnShowSharePicker,
|
base::BindOnce(&SharingServiceOperation::OnShowSharePicker,
|
||||||
weak_factory_.GetWeakPtr()));
|
weak_factory_.GetWeakPtr()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SharingServiceOperation::OnShowSharePicker(
|
void SharingServiceOperation::OnShowSharePicker(
|
||||||
blink::mojom::ShareError error) {
|
blink::mojom::ShareError error) {
|
||||||
|
if (file_paths_.size() > 0) {
|
||||||
|
PrepareDirectoryTask::ScheduleSharedFileDeletion(
|
||||||
|
std::move(file_paths_), base::TimeDelta::FromMinutes(0));
|
||||||
|
}
|
||||||
std::move(callback_).Run(error);
|
std::move(callback_).Run(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,15 +158,15 @@ void SharingServiceOperation::ShowSharePicker(
|
|||||||
const std::vector<base::FilePath>& file_paths,
|
const std::vector<base::FilePath>& file_paths,
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const std::string& title,
|
const std::string& title,
|
||||||
|
const GURL& url,
|
||||||
blink::mojom::ShareService::ShareCallback callback) {
|
blink::mojom::ShareService::ShareCallback callback) {
|
||||||
std::vector<std::string> file_paths_as_utf8;
|
std::vector<std::string> file_paths_as_utf8;
|
||||||
for (const auto& file_path : file_paths) {
|
for (const auto& file_path : file_paths) {
|
||||||
file_paths_as_utf8.emplace_back(file_path.AsUTF8Unsafe());
|
file_paths_as_utf8.emplace_back(file_path.AsUTF8Unsafe());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(crbug.com/1144920): Add & invoke NSSharingServicePicker in
|
web_contents->GetRenderWidgetHostView()->ShowSharePicker(
|
||||||
// remote_cocoa
|
title, text, url.spec(), file_paths_as_utf8, std::move(callback));
|
||||||
std::move(callback).Run(blink::mojom::ShareError::INTERNAL_ERROR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
// Copyright 2021 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/webshare/mac/sharing_service_operation.h"
|
||||||
|
|
||||||
|
#include "base/test/bind.h"
|
||||||
|
#include "base/test/scoped_feature_list.h"
|
||||||
|
#include "chrome/browser/ui/browser.h"
|
||||||
|
#include "chrome/browser/ui/tabs/tab_strip_model.h"
|
||||||
|
#include "chrome/common/chrome_features.h"
|
||||||
|
#include "chrome/test/base/in_process_browser_test.h"
|
||||||
|
#include "chrome/test/base/ui_test_utils.h"
|
||||||
|
#include "content/public/test/browser_test.h"
|
||||||
|
#include "content/public/test/browser_test_utils.h"
|
||||||
|
#include "net/test/embedded_test_server/embedded_test_server.h"
|
||||||
|
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
|
||||||
|
namespace webshare {
|
||||||
|
|
||||||
|
class SharingServiceOperationBrowserTest : public InProcessBrowserTest {
|
||||||
|
public:
|
||||||
|
SharingServiceOperationBrowserTest() {
|
||||||
|
feature_list_.InitAndEnableFeature(features::kWebShare);
|
||||||
|
}
|
||||||
|
|
||||||
|
GURL GetAppUrl() const {
|
||||||
|
return embedded_test_server()->GetURL("/webshare/index.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
base::test::ScopedFeatureList feature_list_;
|
||||||
|
};
|
||||||
|
|
||||||
|
IN_PROC_BROWSER_TEST_F(SharingServiceOperationBrowserTest,
|
||||||
|
ShareIllegalFilename) {
|
||||||
|
const std::string script =
|
||||||
|
"share_multiple_custom_files_url('../sample.csv', '..sample.csv')";
|
||||||
|
ASSERT_TRUE(embedded_test_server()->Start());
|
||||||
|
ui_test_utils::NavigateToURL(browser(), GetAppUrl());
|
||||||
|
content::WebContents* const contents =
|
||||||
|
browser()->tab_strip_model()->GetActiveWebContents();
|
||||||
|
std::vector<base::FilePath> file_paths;
|
||||||
|
|
||||||
|
ui_test_utils::NavigateToURL(browser(), GetAppUrl());
|
||||||
|
SharingServiceOperation::SetSharePickerCallbackForTesting(
|
||||||
|
base::BindLambdaForTesting(
|
||||||
|
[](content::WebContents* in_contents,
|
||||||
|
const std::vector<base::FilePath>& file_paths,
|
||||||
|
const std::string& text, const std::string& title, const GURL& url,
|
||||||
|
blink::mojom::ShareService::ShareCallback close_callback) {
|
||||||
|
EXPECT_EQ(file_paths[0].BaseName().value(), "_._sample.csv");
|
||||||
|
EXPECT_EQ(file_paths[1].BaseName().value(), "_.sample.csv");
|
||||||
|
std::move(close_callback).Run(blink::mojom::ShareError::OK);
|
||||||
|
}));
|
||||||
|
|
||||||
|
EXPECT_EQ("share succeeded", content::EvalJs(contents, script));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webshare
|
@ -67,6 +67,7 @@ class ShareServiceBrowserTest : public InProcessBrowserTest {
|
|||||||
const std::vector<base::FilePath>& file_paths,
|
const std::vector<base::FilePath>& file_paths,
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const std::string& title,
|
const std::string& title,
|
||||||
|
const GURL& url,
|
||||||
blink::mojom::ShareService::ShareCallback close_callback) {
|
blink::mojom::ShareService::ShareCallback close_callback) {
|
||||||
std::move(close_callback).Run(blink::mojom::ShareError::OK);
|
std::move(close_callback).Run(blink::mojom::ShareError::OK);
|
||||||
}
|
}
|
||||||
|
@ -155,6 +155,7 @@ class ShareServiceUnitTest : public ChromeRenderViewHostTestHarness {
|
|||||||
const std::vector<base::FilePath>& file_paths,
|
const std::vector<base::FilePath>& file_paths,
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
const std::string& title,
|
const std::string& title,
|
||||||
|
const GURL& url,
|
||||||
blink::mojom::ShareService::ShareCallback close_callback) {
|
blink::mojom::ShareService::ShareCallback close_callback) {
|
||||||
std::move(close_callback).Run(blink::mojom::ShareError::OK);
|
std::move(close_callback).Run(blink::mojom::ShareError::OK);
|
||||||
}
|
}
|
||||||
|
@ -1861,6 +1861,11 @@ if (!is_android) {
|
|||||||
sources += [ "../browser/webshare/share_service_browsertest.cc" ]
|
sources += [ "../browser/webshare/share_service_browsertest.cc" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_mac) {
|
||||||
|
sources +=
|
||||||
|
[ "../browser/webshare/mac/sharing_service_operation_browsertest.cc" ]
|
||||||
|
}
|
||||||
|
|
||||||
if (enable_dice_support) {
|
if (enable_dice_support) {
|
||||||
sources += [
|
sources += [
|
||||||
"../browser/policy/cloud/user_policy_signin_service_browsertest.cc",
|
"../browser/policy/cloud/user_policy_signin_service_browsertest.cc",
|
||||||
|
@ -142,6 +142,19 @@
|
|||||||
return ('share failed: ' + error);
|
return ('share failed: ' + error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function share_multiple_custom_files_url(first_filename, second_filename) {
|
||||||
|
try {
|
||||||
|
const first_file = create_file(first_filename, 'text/csv', 12);
|
||||||
|
const second_file = create_file(second_filename, 'text/csv', 15);
|
||||||
|
await navigator.share({files: [first_file, second_file],
|
||||||
|
url: "https://example.com/"});
|
||||||
|
return 'share succeeded';
|
||||||
|
} catch(error) {
|
||||||
|
return ('share failed: ' + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -31,4 +31,5 @@ include_rules = [
|
|||||||
"+content/public/common/content_features.h",
|
"+content/public/common/content_features.h",
|
||||||
"+content/public/common/drop_data.h",
|
"+content/public/common/drop_data.h",
|
||||||
"+content/public/common/widget_type.h",
|
"+content/public/common/widget_type.h",
|
||||||
|
"+third_party/blink/public/mojom/webshare/webshare.mojom.h",
|
||||||
]
|
]
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#import "base/mac/scoped_nsobject.h"
|
#import "base/mac/scoped_nsobject.h"
|
||||||
#import "content/app_shim_remote_cocoa/popup_window_mac.h"
|
#import "content/app_shim_remote_cocoa/popup_window_mac.h"
|
||||||
#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
|
#import "content/app_shim_remote_cocoa/render_widget_host_view_cocoa.h"
|
||||||
|
#include "content/app_shim_remote_cocoa/sharing_service_picker.h"
|
||||||
#include "content/common/render_widget_host_ns_view.mojom.h"
|
#include "content/common/render_widget_host_ns_view.mojom.h"
|
||||||
#include "content/public/common/widget_type.h"
|
#include "content/public/common/widget_type.h"
|
||||||
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
||||||
@ -68,6 +69,12 @@ class RenderWidgetHostNSViewBridge : public mojom::RenderWidgetHostNSView,
|
|||||||
void LockKeyboard(
|
void LockKeyboard(
|
||||||
const base::Optional<std::vector<uint32_t>>& uint_dom_codes) override;
|
const base::Optional<std::vector<uint32_t>>& uint_dom_codes) override;
|
||||||
void UnlockKeyboard() override;
|
void UnlockKeyboard() override;
|
||||||
|
void ShowSharingServicePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
ShowSharingServicePickerCallback callback) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsPopup() const { return !!popup_window_; }
|
bool IsPopup() const { return !!popup_window_; }
|
||||||
|
@ -271,4 +271,14 @@ void RenderWidgetHostNSViewBridge::UnlockKeyboard() {
|
|||||||
[cocoa_view_ unlockKeyboard];
|
[cocoa_view_ unlockKeyboard];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderWidgetHostNSViewBridge::ShowSharingServicePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
ShowSharingServicePickerCallback callback) {
|
||||||
|
ShowSharingServicePickerForView(cocoa_view_, title, text, url, file_paths,
|
||||||
|
std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace remote_cocoa
|
} // namespace remote_cocoa
|
||||||
|
26
content/app_shim_remote_cocoa/sharing_service_picker.h
Normal file
26
content/app_shim_remote_cocoa/sharing_service_picker.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2021 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 CONTENT_APP_SHIM_REMOTE_COCOA_SHARING_SERVICE_PICKER_H_
|
||||||
|
#define CONTENT_APP_SHIM_REMOTE_COCOA_SHARING_SERVICE_PICKER_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
#include "content/common/render_widget_host_ns_view.mojom.h"
|
||||||
|
|
||||||
|
namespace remote_cocoa {
|
||||||
|
|
||||||
|
void ShowSharingServicePickerForView(
|
||||||
|
NSView* owning_view,
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
mojom::RenderWidgetHostNSView::ShowSharingServicePickerCallback callback);
|
||||||
|
|
||||||
|
} // namespace remote_cocoa
|
||||||
|
|
||||||
|
#endif // CONTENT_APP_SHIM_REMOTE_COCOA_SHARING_SERVICE_PICKER_H_
|
114
content/app_shim_remote_cocoa/sharing_service_picker.mm
Normal file
114
content/app_shim_remote_cocoa/sharing_service_picker.mm
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// Copyright 2021 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 "content/app_shim_remote_cocoa/sharing_service_picker.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "base/mac/scoped_nsobject.h"
|
||||||
|
#include "base/strings/sys_string_conversions.h"
|
||||||
|
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
|
||||||
|
@interface SharingServicePicker
|
||||||
|
: NSObject <NSSharingServiceDelegate, NSSharingServicePickerDelegate>
|
||||||
|
// Displays the NSSharingServicePicker which is positioned center and overlaps
|
||||||
|
// WebContents and the Non Client area.
|
||||||
|
- (void)show;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation SharingServicePicker {
|
||||||
|
base::scoped_nsobject<NSSharingServicePicker> picker_;
|
||||||
|
remote_cocoa::mojom::RenderWidgetHostNSView::ShowSharingServicePickerCallback
|
||||||
|
callback_;
|
||||||
|
NSView* view_;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithItems:(NSArray*)items
|
||||||
|
callback:(remote_cocoa::mojom::RenderWidgetHostNSView::
|
||||||
|
ShowSharingServicePickerCallback)cb
|
||||||
|
view:(NSView*)view {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
picker_.reset([[NSSharingServicePicker alloc] initWithItems:items]);
|
||||||
|
picker_.get().delegate = self;
|
||||||
|
callback_ = std::move(cb);
|
||||||
|
view_ = view;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sharingServicePicker:(NSSharingServicePicker*)sharingServicePicker
|
||||||
|
didChooseSharingService:(NSSharingService*)service {
|
||||||
|
// When the NSSharingServicePicker gets invoked but then the picker gets
|
||||||
|
// dismissed, this is the only delegate method called, and it's called with a
|
||||||
|
// nil service, so run the callback.
|
||||||
|
if (!service) {
|
||||||
|
std::move(callback_).Run(blink::mojom::ShareError::CANCELED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)show {
|
||||||
|
NSRect viewFrame = [view_ frame];
|
||||||
|
CGSize size = viewFrame.size;
|
||||||
|
NSRect rect = NSMakeRect(size.width / 2, size.height, 1, 1);
|
||||||
|
[picker_ showRelativeToRect:rect ofView:view_ preferredEdge:NSMaxXEdge];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sharingService:(NSSharingService*)sharingService
|
||||||
|
didShareItems:(NSArray*)items {
|
||||||
|
std::move(callback_).Run(blink::mojom::ShareError::OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sharingService:(NSSharingService*)sharingService
|
||||||
|
didFailToShareItems:(NSArray*)items
|
||||||
|
error:(NSError*)error {
|
||||||
|
error.code == NSUserCancelledError
|
||||||
|
? std::move(callback_).Run(blink::mojom::ShareError::CANCELED)
|
||||||
|
: std::move(callback_).Run(blink::mojom::ShareError::INTERNAL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<NSSharingServiceDelegate>)
|
||||||
|
sharingServicePicker:(NSSharingServicePicker*)sharingServicePicker
|
||||||
|
delegateForSharingService:(NSSharingService*)sharingService {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSWindow*)sharingService:(NSSharingService*)sharingService
|
||||||
|
sourceWindowForShareItems:(NSArray*)items
|
||||||
|
sharingContentScope:(NSSharingContentScope*)sharingContentScope {
|
||||||
|
return [view_ window];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
namespace remote_cocoa {
|
||||||
|
|
||||||
|
void ShowSharingServicePickerForView(
|
||||||
|
NSView* view,
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
mojom::RenderWidgetHostNSView::ShowSharingServicePickerCallback callback) {
|
||||||
|
NSString* ns_title = base::SysUTF8ToNSString(title);
|
||||||
|
NSString* ns_url = base::SysUTF8ToNSString(url);
|
||||||
|
NSString* ns_text = base::SysUTF8ToNSString(text);
|
||||||
|
|
||||||
|
NSMutableArray* items =
|
||||||
|
[NSMutableArray arrayWithArray:@[ ns_title, ns_url, ns_text ]];
|
||||||
|
|
||||||
|
for (const auto& file_path : file_paths) {
|
||||||
|
NSString* ns_file_path = base::SysUTF8ToNSString(file_path);
|
||||||
|
NSURL* file_url = [NSURL fileURLWithPath:ns_file_path];
|
||||||
|
[items addObject:file_url];
|
||||||
|
}
|
||||||
|
|
||||||
|
base::scoped_nsobject<SharingServicePicker> picker(
|
||||||
|
[[SharingServicePicker alloc] initWithItems:items
|
||||||
|
callback:std::move(callback)
|
||||||
|
view:view]);
|
||||||
|
[picker.get() show];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace remote_cocoa
|
@ -2742,6 +2742,8 @@ source_set("browser") {
|
|||||||
"../app_shim_remote_cocoa/render_widget_host_ns_view_host_helper.h",
|
"../app_shim_remote_cocoa/render_widget_host_ns_view_host_helper.h",
|
||||||
"../app_shim_remote_cocoa/render_widget_host_view_cocoa.h",
|
"../app_shim_remote_cocoa/render_widget_host_view_cocoa.h",
|
||||||
"../app_shim_remote_cocoa/render_widget_host_view_cocoa.mm",
|
"../app_shim_remote_cocoa/render_widget_host_view_cocoa.mm",
|
||||||
|
"../app_shim_remote_cocoa/sharing_service_picker.h",
|
||||||
|
"../app_shim_remote_cocoa/sharing_service_picker.mm",
|
||||||
"../app_shim_remote_cocoa/web_contents_view_cocoa.h",
|
"../app_shim_remote_cocoa/web_contents_view_cocoa.h",
|
||||||
"../app_shim_remote_cocoa/web_contents_view_cocoa.mm",
|
"../app_shim_remote_cocoa/web_contents_view_cocoa.mm",
|
||||||
]
|
]
|
||||||
|
@ -755,6 +755,13 @@ void RenderWidgetHostViewChildFrame::SpeakSelection() {}
|
|||||||
|
|
||||||
void RenderWidgetHostViewChildFrame::SetWindowFrameInScreen(
|
void RenderWidgetHostViewChildFrame::SetWindowFrameInScreen(
|
||||||
const gfx::Rect& rect) {}
|
const gfx::Rect& rect) {}
|
||||||
|
|
||||||
|
void RenderWidgetHostViewChildFrame::ShowSharePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
blink::mojom::ShareService::ShareCallback callback) {}
|
||||||
#endif // defined(OS_MAC)
|
#endif // defined(OS_MAC)
|
||||||
|
|
||||||
void RenderWidgetHostViewChildFrame::CopyFromSurface(
|
void RenderWidgetHostViewChildFrame::CopyFromSurface(
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
#include "ui/gfx/geometry/rect.h"
|
#include "ui/gfx/geometry/rect.h"
|
||||||
#include "ui/gfx/native_widget_types.h"
|
#include "ui/gfx/native_widget_types.h"
|
||||||
|
|
||||||
|
#if defined(OS_MAC)
|
||||||
|
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
|
||||||
|
#endif // defined(OS_MAC)
|
||||||
|
|
||||||
namespace content {
|
namespace content {
|
||||||
class CrossProcessFrameConnector;
|
class CrossProcessFrameConnector;
|
||||||
class RenderWidgetHost;
|
class RenderWidgetHost;
|
||||||
@ -147,6 +151,12 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
|
|||||||
void ShowDefinitionForSelection() override;
|
void ShowDefinitionForSelection() override;
|
||||||
void SpeakSelection() override;
|
void SpeakSelection() override;
|
||||||
void SetWindowFrameInScreen(const gfx::Rect& rect) override;
|
void SetWindowFrameInScreen(const gfx::Rect& rect) override;
|
||||||
|
void ShowSharePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
blink::mojom::ShareService::ShareCallback callback) override;
|
||||||
#endif // defined(OS_MAC)
|
#endif // defined(OS_MAC)
|
||||||
|
|
||||||
blink::mojom::InputEventResultState FilterInputEvent(
|
blink::mojom::InputEventResultState FilterInputEvent(
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "content/common/render_widget_host_ns_view.mojom.h"
|
#include "content/common/render_widget_host_ns_view.mojom.h"
|
||||||
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
||||||
#include "mojo/public/cpp/bindings/associated_remote.h"
|
#include "mojo/public/cpp/bindings/associated_remote.h"
|
||||||
|
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
|
||||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||||
#include "ui/base/cocoa/accessibility_focus_overrider.h"
|
#include "ui/base/cocoa/accessibility_focus_overrider.h"
|
||||||
#include "ui/base/cocoa/remote_layer_api.h"
|
#include "ui/base/cocoa/remote_layer_api.h"
|
||||||
@ -479,6 +480,13 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
|
|||||||
|
|
||||||
MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
|
MouseWheelPhaseHandler* GetMouseWheelPhaseHandler() override;
|
||||||
|
|
||||||
|
void ShowSharePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
blink::mojom::ShareService::ShareCallback callback) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This class is to be deleted through the Destroy method.
|
// This class is to be deleted through the Destroy method.
|
||||||
~RenderWidgetHostViewMac() override;
|
~RenderWidgetHostViewMac() override;
|
||||||
|
@ -1412,6 +1412,16 @@ MouseWheelPhaseHandler* RenderWidgetHostViewMac::GetMouseWheelPhaseHandler() {
|
|||||||
return &mouse_wheel_phase_handler_;
|
return &mouse_wheel_phase_handler_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderWidgetHostViewMac::ShowSharePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
blink::mojom::ShareService::ShareCallback callback) {
|
||||||
|
ns_view_->ShowSharingServicePicker(title, text, url, file_paths,
|
||||||
|
std::move(callback));
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// RenderWidgetHostNSViewHostHelper and mojom::RenderWidgetHostNSViewHost
|
// RenderWidgetHostNSViewHostHelper and mojom::RenderWidgetHostNSViewHost
|
||||||
// implementation:
|
// implementation:
|
||||||
|
@ -6,6 +6,7 @@ module remote_cocoa.mojom;
|
|||||||
|
|
||||||
import "mojo/public/mojom/base/string16.mojom";
|
import "mojo/public/mojom/base/string16.mojom";
|
||||||
import "third_party/blink/public/mojom/input/input_handler.mojom";
|
import "third_party/blink/public/mojom/input/input_handler.mojom";
|
||||||
|
import "third_party/blink/public/mojom/webshare/share_error.mojom";
|
||||||
import "ui/base/mojom/attributed_string.mojom";
|
import "ui/base/mojom/attributed_string.mojom";
|
||||||
import "ui/base/cursor/mojom/cursor.mojom";
|
import "ui/base/cursor/mojom/cursor.mojom";
|
||||||
import "ui/base/ime/mojom/ime_types.mojom";
|
import "ui/base/ime/mojom/ime_types.mojom";
|
||||||
@ -92,6 +93,14 @@ interface RenderWidgetHostNSView {
|
|||||||
|
|
||||||
// Stop intercepting keyboard events.
|
// Stop intercepting keyboard events.
|
||||||
UnlockKeyboard();
|
UnlockKeyboard();
|
||||||
|
|
||||||
|
// Show the NSSharingServicePicker using the requested data that is passed and
|
||||||
|
// returning the result of that action.
|
||||||
|
ShowSharingServicePicker(string title,
|
||||||
|
string text,
|
||||||
|
string url,
|
||||||
|
array<string> file_paths)
|
||||||
|
=> (blink.mojom.ShareError error);
|
||||||
};
|
};
|
||||||
|
|
||||||
// The interface through which the RenderWidgetHostViewCocoa NSView in the app
|
// The interface through which the RenderWidgetHostViewCocoa NSView in the app
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
#include "ui/gfx/native_widget_types.h"
|
#include "ui/gfx/native_widget_types.h"
|
||||||
#include "ui/gfx/range/range.h"
|
#include "ui/gfx/range/range.h"
|
||||||
|
|
||||||
|
#if defined(OS_MAC)
|
||||||
|
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace gfx {
|
namespace gfx {
|
||||||
class Insets;
|
class Insets;
|
||||||
class Point;
|
class Point;
|
||||||
@ -258,6 +262,23 @@ class CONTENT_EXPORT RenderWidgetHostView {
|
|||||||
// Allows to update the widget's screen rects when it is not attached to
|
// Allows to update the widget's screen rects when it is not attached to
|
||||||
// a window (e.g. in headless mode).
|
// a window (e.g. in headless mode).
|
||||||
virtual void SetWindowFrameInScreen(const gfx::Rect& rect) = 0;
|
virtual void SetWindowFrameInScreen(const gfx::Rect& rect) = 0;
|
||||||
|
|
||||||
|
// Invoked by browser implementation of the navigator.share() to trigger the
|
||||||
|
// NSSharingServicePicker.
|
||||||
|
//
|
||||||
|
// |title|, |text|, |url| makes up the requested data that is passed to the
|
||||||
|
// picker after being converted to NSString.
|
||||||
|
// |file_paths| is the set of paths to files to be shared passed onto the
|
||||||
|
// picker after being converted to NSURL.
|
||||||
|
// |callback| returns the result from the NSSharingServicePicker depending
|
||||||
|
// upon the user's action.
|
||||||
|
virtual void ShowSharePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
blink::mojom::ShareService::ShareCallback callback) = 0;
|
||||||
|
|
||||||
#endif // defined(OS_MAC)
|
#endif // defined(OS_MAC)
|
||||||
|
|
||||||
// Indicates that this view should show the contents of |view| if it doesn't
|
// Indicates that this view should show the contents of |view| if it doesn't
|
||||||
|
@ -160,6 +160,13 @@ void TestRenderWidgetHostView::SpeakSelection() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TestRenderWidgetHostView::SetWindowFrameInScreen(const gfx::Rect& rect) {}
|
void TestRenderWidgetHostView::SetWindowFrameInScreen(const gfx::Rect& rect) {}
|
||||||
|
|
||||||
|
void TestRenderWidgetHostView::ShowSharePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
blink::mojom::ShareService::ShareCallback callback) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gfx::Rect TestRenderWidgetHostView::GetBoundsInRootWindow() {
|
gfx::Rect TestRenderWidgetHostView::GetBoundsInRootWindow() {
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
#include "ui/aura/window.h"
|
#include "ui/aura/window.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_MAC)
|
||||||
|
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// This file provides a testing framework for mocking out the RenderProcessHost
|
// This file provides a testing framework for mocking out the RenderProcessHost
|
||||||
// layer. It allows you to test RenderViewHost, WebContentsImpl,
|
// layer. It allows you to test RenderViewHost, WebContentsImpl,
|
||||||
// NavigationController, and other layers above that without running an actual
|
// NavigationController, and other layers above that without running an actual
|
||||||
@ -77,6 +81,12 @@ class TestRenderWidgetHostView : public RenderWidgetHostViewBase,
|
|||||||
void ShowDefinitionForSelection() override {}
|
void ShowDefinitionForSelection() override {}
|
||||||
void SpeakSelection() override;
|
void SpeakSelection() override;
|
||||||
void SetWindowFrameInScreen(const gfx::Rect& rect) override;
|
void SetWindowFrameInScreen(const gfx::Rect& rect) override;
|
||||||
|
void ShowSharePicker(
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& text,
|
||||||
|
const std::string& url,
|
||||||
|
const std::vector<std::string>& file_paths,
|
||||||
|
blink::mojom::ShareService::ShareCallback callback) override;
|
||||||
#endif // defined(OS_MAC)
|
#endif // defined(OS_MAC)
|
||||||
|
|
||||||
// Advances the fallback surface to the first surface after navigation. This
|
// Advances the fallback surface to the first surface after navigation. This
|
||||||
|
Reference in New Issue
Block a user