Commit 8f63ed8f authored by Richard Knoll's avatar Richard Knoll Committed by Commit Bot

[Nearby] Add mojo interface for discovery and confirmation pages

This adds a mojo interface for the discovery page to find nearby devices
and connect to one. For unknown devices we require an additional
confirmation step to verify a connection id. The user has the option to
accept or reject on the nearby-confirmation-page.

Bug: 1099710
Change-Id: I308a7926efef61a3fa872051b00fcf35e62a8287
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2235516
Commit-Queue: Richard Knoll <knollr@chromium.org>
Reviewed-by: default avatarAlex Gough <ajgo@chromium.org>
Reviewed-by: default avatarAlex Chau <alexchau@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarJames Vecore <vecore@google.com>
Cr-Commit-Position: refs/heads/master@{#790643}
parent 159006da
...@@ -3309,6 +3309,8 @@ static_library("browser") { ...@@ -3309,6 +3309,8 @@ static_library("browser") {
"nearby_sharing/instantmessaging/stream_parser.h", "nearby_sharing/instantmessaging/stream_parser.h",
"nearby_sharing/instantmessaging/token_fetcher.cc", "nearby_sharing/instantmessaging/token_fetcher.cc",
"nearby_sharing/instantmessaging/token_fetcher.h", "nearby_sharing/instantmessaging/token_fetcher.h",
"nearby_sharing/nearby_confirmation_manager.cc",
"nearby_sharing/nearby_confirmation_manager.h",
"nearby_sharing/nearby_connection.h", "nearby_sharing/nearby_connection.h",
"nearby_sharing/nearby_connections_manager.h", "nearby_sharing/nearby_connections_manager.h",
"nearby_sharing/nearby_connections_manager_impl.cc", "nearby_sharing/nearby_connections_manager_impl.cc",
...@@ -3317,6 +3319,8 @@ static_library("browser") { ...@@ -3317,6 +3319,8 @@ static_library("browser") {
"nearby_sharing/nearby_notification_handler.h", "nearby_sharing/nearby_notification_handler.h",
"nearby_sharing/nearby_notification_manager.cc", "nearby_sharing/nearby_notification_manager.cc",
"nearby_sharing/nearby_notification_manager.h", "nearby_sharing/nearby_notification_manager.h",
"nearby_sharing/nearby_per_session_discovery_manager.cc",
"nearby_sharing/nearby_per_session_discovery_manager.h",
"nearby_sharing/nearby_process_manager.cc", "nearby_sharing/nearby_process_manager.cc",
"nearby_sharing/nearby_process_manager.h", "nearby_sharing/nearby_process_manager.h",
"nearby_sharing/nearby_sharing_service.h", "nearby_sharing/nearby_sharing_service.h",
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/accessibility/accessibility_labels_service.h" #include "chrome/browser/accessibility/accessibility_labels_service.h"
#include "chrome/browser/accessibility/accessibility_labels_service_factory.h" #include "chrome/browser/accessibility/accessibility_labels_service_factory.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/buildflags.h" #include "chrome/browser/buildflags.h"
#include "chrome/browser/dom_distiller/dom_distiller_service_factory.h" #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
#include "chrome/browser/engagement/site_engagement_details.mojom.h" #include "chrome/browser/engagement/site_engagement_details.mojom.h"
...@@ -112,6 +113,8 @@ ...@@ -112,6 +113,8 @@
#include "chrome/browser/ui/webui/downloads/downloads.mojom.h" #include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
#include "chrome/browser/ui/webui/downloads/downloads_ui.h" #include "chrome/browser/ui/webui/downloads/downloads_ui.h"
#include "chrome/browser/ui/webui/media/media_feeds_ui.h" #include "chrome/browser/ui/webui/media/media_feeds_ui.h"
#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
#include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h"
#include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h" #include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h"
...@@ -497,6 +500,12 @@ void PopulateChromeWebUIFrameBinders( ...@@ -497,6 +500,12 @@ void PopulateChromeWebUIFrameBinders(
RegisterWebUIControllerInterfaceBinder<downloads::mojom::PageHandlerFactory, RegisterWebUIControllerInterfaceBinder<downloads::mojom::PageHandlerFactory,
DownloadsUI>(map); DownloadsUI>(map);
if (base::FeatureList::IsEnabled(features::kNearbySharing)) {
RegisterWebUIControllerInterfaceBinder<
nearby_share::mojom::DiscoveryManager,
nearby_share::NearbyShareDialogUI>(map);
}
RegisterWebUIControllerInterfaceBinder< RegisterWebUIControllerInterfaceBinder<
new_tab_page::mojom::PageHandlerFactory, NewTabPageUI>(map); new_tab_page::mojom::PageHandlerFactory, NewTabPageUI>(map);
......
// 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/nearby_sharing/mock_nearby_sharing_service.h"
MockNearbySharingService::MockNearbySharingService() = default;
MockNearbySharingService::~MockNearbySharingService() = default;
// 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_NEARBY_SHARING_MOCK_NEARBY_SHARING_SERVICE_H_
#define CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_SHARING_SERVICE_H_
#include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
#include "testing/gmock/include/gmock/gmock.h"
class MockNearbySharingService : public NearbySharingService {
public:
MockNearbySharingService();
~MockNearbySharingService() override;
// NearbySharingService:
MOCK_METHOD(StatusCodes,
RegisterSendSurface,
(TransferUpdateCallback*, ShareTargetDiscoveredCallback*),
(override));
MOCK_METHOD(StatusCodes,
UnregisterSendSurface,
(TransferUpdateCallback*, ShareTargetDiscoveredCallback*),
(override));
MOCK_METHOD(StatusCodes,
RegisterReceiveSurface,
(TransferUpdateCallback*, ReceiveSurfaceState),
(override));
MOCK_METHOD(StatusCodes,
UnregisterReceiveSurface,
(TransferUpdateCallback*),
(override));
MOCK_METHOD(void,
SendText,
(const ShareTarget&, std::string, StatusCodesCallback),
(override));
MOCK_METHOD(void,
SendFiles,
(const ShareTarget&,
const std::vector<base::FilePath>&,
StatusCodesCallback),
(override));
MOCK_METHOD(void,
Accept,
(const ShareTarget&, StatusCodesCallback),
(override));
MOCK_METHOD(void,
Reject,
(const ShareTarget&, StatusCodesCallback),
(override));
MOCK_METHOD(void,
Cancel,
(const ShareTarget&, StatusCodesCallback),
(override));
MOCK_METHOD(void,
Open,
(const ShareTarget&, StatusCodesCallback),
(override));
};
#endif // CHROME_BROWSER_NEARBY_SHARING_MOCK_NEARBY_SHARING_SERVICE_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/nearby_sharing/nearby_confirmation_manager.h"
#include "base/bind.h"
#include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
#include "content/public/browser/browser_thread.h"
namespace {
NearbySharingService::StatusCodesCallback ToStatusCodesCallback(
base::OnceCallback<void(bool)> callback) {
return base::BindOnce(
[](base::OnceCallback<void(bool)> callback,
NearbySharingService::StatusCodes status) {
std::move(callback).Run(status ==
NearbySharingService::StatusCodes::kOk);
},
std::move(callback));
}
} // namespace
NearbyConfirmationManager::NearbyConfirmationManager(
NearbySharingService* nearby_service,
ShareTarget share_target)
: nearby_service_(nearby_service), share_target_(std::move(share_target)) {
DCHECK(nearby_service_);
}
NearbyConfirmationManager::~NearbyConfirmationManager() = default;
void NearbyConfirmationManager::Accept(AcceptCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
nearby_service_->Accept(share_target_,
ToStatusCodesCallback(std::move(callback)));
}
void NearbyConfirmationManager::Reject(RejectCallback callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
nearby_service_->Reject(share_target_,
ToStatusCodesCallback(std::move(callback)));
}
// 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_NEARBY_SHARING_NEARBY_CONFIRMATION_MANAGER_H_
#define CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONFIRMATION_MANAGER_H_
#include "chrome/browser/nearby_sharing/share_target.h"
#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
#include <string>
class NearbySharingService;
class NearbyConfirmationManager
: public nearby_share::mojom::ConfirmationManager {
public:
NearbyConfirmationManager(NearbySharingService* nearby_service,
ShareTarget share_target);
NearbyConfirmationManager(const NearbyConfirmationManager&) = delete;
NearbyConfirmationManager& operator=(const NearbyConfirmationManager&) =
delete;
~NearbyConfirmationManager() override;
// nearby_share::mojom::ConfirmationManager:
void Accept(AcceptCallback callback) override;
void Reject(RejectCallback callback) override;
private:
NearbySharingService* nearby_service_;
ShareTarget share_target_;
};
#endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_CONFIRMATION_MANAGER_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/nearby_sharing/nearby_confirmation_manager.h"
#include "base/test/mock_callback.h"
#include "chrome/browser/nearby_sharing/mock_nearby_sharing_service.h"
#include "chrome/browser/nearby_sharing/share_target.h"
#include "chrome/browser/nearby_sharing/share_target_builder.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class NearbyConfirmationManagerTest : public testing::Test {
public:
NearbyConfirmationManagerTest() = default;
~NearbyConfirmationManagerTest() override = default;
MockNearbySharingService& sharing_service() { return sharing_service_; }
NearbyConfirmationManager& manager() { return manager_; }
private:
content::BrowserTaskEnvironment task_environment_;
MockNearbySharingService sharing_service_;
ShareTarget share_target_ = ShareTargetBuilder().build();
NearbyConfirmationManager manager_{&sharing_service_, share_target_};
};
} // namespace
TEST_F(NearbyConfirmationManagerTest, Accept_Success) {
EXPECT_CALL(sharing_service(), Accept(testing::_, testing::_))
.WillOnce(testing::Invoke(
[](const ShareTarget&,
NearbySharingService::StatusCodesCallback callback) {
std::move(callback).Run(NearbySharingService::StatusCodes::kOk);
}));
base::MockCallback<NearbyConfirmationManager::AcceptCallback> callback;
EXPECT_CALL(callback, Run(testing::Eq(true)));
manager().Accept(callback.Get());
}
TEST_F(NearbyConfirmationManagerTest, Accept_Error) {
EXPECT_CALL(sharing_service(), Accept(testing::_, testing::_))
.WillOnce(testing::Invoke(
[](const ShareTarget&,
NearbySharingService::StatusCodesCallback callback) {
std::move(callback).Run(NearbySharingService::StatusCodes::kError);
}));
base::MockCallback<NearbyConfirmationManager::AcceptCallback> callback;
EXPECT_CALL(callback, Run(testing::Eq(false)));
manager().Accept(callback.Get());
}
TEST_F(NearbyConfirmationManagerTest, Reject_Success) {
EXPECT_CALL(sharing_service(), Reject(testing::_, testing::_))
.WillOnce(testing::Invoke(
[](const ShareTarget&,
NearbySharingService::StatusCodesCallback callback) {
std::move(callback).Run(NearbySharingService::StatusCodes::kOk);
}));
base::MockCallback<NearbyConfirmationManager::RejectCallback> callback;
EXPECT_CALL(callback, Run(testing::Eq(true)));
manager().Reject(callback.Get());
}
TEST_F(NearbyConfirmationManagerTest, Reject_Error) {
EXPECT_CALL(sharing_service(), Reject(testing::_, testing::_))
.WillOnce(testing::Invoke(
[](const ShareTarget&,
NearbySharingService::StatusCodesCallback callback) {
std::move(callback).Run(NearbySharingService::StatusCodes::kError);
}));
base::MockCallback<NearbyConfirmationManager::RejectCallback> callback;
EXPECT_CALL(callback, Run(testing::Eq(false)));
manager().Reject(callback.Get());
}
...@@ -12,7 +12,9 @@ ...@@ -12,7 +12,9 @@
#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/browser_features.h" #include "chrome/browser/browser_features.h"
#include "chrome/browser/nearby_sharing/share_target.h" #include "chrome/browser/nearby_sharing/share_target.h"
#include "chrome/browser/nearby_sharing/share_target_builder.h"
#include "chrome/browser/nearby_sharing/transfer_metadata.h" #include "chrome/browser/nearby_sharing/transfer_metadata.h"
#include "chrome/browser/nearby_sharing/transfer_metadata_builder.h"
#include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
...@@ -23,67 +25,6 @@ ...@@ -23,67 +25,6 @@
namespace { namespace {
class ShareTargetBuilder {
public:
ShareTargetBuilder() = default;
~ShareTargetBuilder() = default;
ShareTargetBuilder& set_device_name(const std::string& device_name) {
device_name_ = device_name;
return *this;
}
ShareTargetBuilder& set_is_incoming(bool is_incoming) {
is_incoming_ = is_incoming;
return *this;
}
ShareTargetBuilder& add_attachment(TextAttachment attachment) {
text_attachments_.push_back(std::move(attachment));
return *this;
}
ShareTargetBuilder& add_attachment(FileAttachment attachment) {
file_attachments_.push_back(std::move(attachment));
return *this;
}
ShareTarget build() const {
return ShareTarget(device_name_,
/*image_url=*/GURL(), ShareTarget::Type::kPhone,
text_attachments_, file_attachments_, is_incoming_,
/*full_name=*/base::nullopt,
/*is_known=*/false);
}
private:
std::string device_name_;
bool is_incoming_ = false;
std::vector<TextAttachment> text_attachments_;
std::vector<FileAttachment> file_attachments_;
};
class TransferMetadataBuilder {
public:
TransferMetadataBuilder() = default;
~TransferMetadataBuilder() = default;
TransferMetadataBuilder& set_progress(double progress) {
progress_ = progress;
return *this;
}
TransferMetadata build() const {
return TransferMetadata(TransferMetadata::Status::kInProgress, progress_,
/*token=*/base::nullopt,
/*is_original=*/false,
/*is_final_status=*/false);
}
private:
double progress_ = 0;
};
TextAttachment CreateTextAttachment(TextAttachment::Type type) { TextAttachment CreateTextAttachment(TextAttachment::Type type) {
return TextAttachment("text body", type, /*size=*/9); return TextAttachment("text body", type, /*size=*/9);
} }
......
// 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/nearby_sharing/nearby_per_session_discovery_manager.h"
#include <string>
#include "base/bind_helpers.h"
#include "base/optional.h"
#include "base/stl_util.h"
#include "chrome/browser/nearby_sharing/logging/logging.h"
#include "chrome/browser/nearby_sharing/nearby_confirmation_manager.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
NearbyPerSessionDiscoveryManager::NearbyPerSessionDiscoveryManager(
NearbySharingService* nearby_sharing_service)
: nearby_sharing_service_(nearby_sharing_service) {}
NearbyPerSessionDiscoveryManager::~NearbyPerSessionDiscoveryManager() {
if (!is_registered_)
return;
NearbySharingService::StatusCodes result =
nearby_sharing_service_->UnregisterSendSurface(this, this);
if (result != NearbySharingService::StatusCodes::kOk)
NS_LOG(WARNING) << "Failed to unregister send surface";
}
void NearbyPerSessionDiscoveryManager::OnTransferUpdate(
const ShareTarget& share_target,
const TransferMetadata& transfer_metadata) {
switch (transfer_metadata.status()) {
case TransferMetadata::Status::kAwaitingLocalConfirmation: {
DCHECK(select_share_target_callback_);
mojo::PendingRemote<nearby_share::mojom::ConfirmationManager> remote;
mojo::MakeSelfOwnedReceiver(std::make_unique<NearbyConfirmationManager>(
nearby_sharing_service_, share_target),
remote.InitWithNewPipeAndPassReceiver());
std::move(select_share_target_callback_)
.Run(nearby_share::mojom::SelectShareTargetResult::kOk,
transfer_metadata.token(), std::move(remote));
break;
}
case TransferMetadata::Status::kAwaitingRemoteAcceptance:
DCHECK(select_share_target_callback_);
std::move(select_share_target_callback_)
.Run(nearby_share::mojom::SelectShareTargetResult::kOk,
/*token=*/base::nullopt, mojo::NullRemote());
break;
default:
break;
}
}
void NearbyPerSessionDiscoveryManager::OnShareTargetDiscovered(
ShareTarget share_target) {
base::UnguessableToken share_target_id = share_target.id();
auto target = nearby_share::mojom::ShareTarget::New(share_target_id);
base::InsertOrAssign(discovered_share_targets_, share_target_id,
std::move(share_target));
share_target_listener_->OnShareTargetDiscovered(std::move(target));
}
void NearbyPerSessionDiscoveryManager::OnShareTargetLost(
ShareTarget share_target) {
base::UnguessableToken share_target_id = share_target.id();
auto target = nearby_share::mojom::ShareTarget::New(share_target.id());
discovered_share_targets_.erase(share_target_id);
share_target_listener_->OnShareTargetLost(std::move(target));
}
void NearbyPerSessionDiscoveryManager::StartDiscovery(
mojo::PendingRemote<nearby_share::mojom::ShareTargetListener> listener,
StartDiscoveryCallback callback) {
DCHECK(!is_registered_);
NearbySharingService::StatusCodes result =
nearby_sharing_service_->RegisterSendSurface(this, this);
if (result != NearbySharingService::StatusCodes::kOk) {
NS_LOG(WARNING) << "Failed to register send surface";
std::move(callback).Run(/*success=*/false);
return;
}
is_registered_ = true;
share_target_listener_.Bind(std::move(listener));
std::move(callback).Run(/*success=*/true);
}
void NearbyPerSessionDiscoveryManager::SelectShareTarget(
nearby_share::mojom::ShareTargetPtr share_target,
SelectShareTargetCallback callback) {
DCHECK(!select_share_target_callback_);
base::UnguessableToken share_target_id = share_target->id;
auto iter = discovered_share_targets_.find(share_target_id);
if (iter == discovered_share_targets_.end()) {
NS_LOG(VERBOSE) << "Unknown share target selected: id=" << share_target_id;
std::move(callback).Run(
nearby_share::mojom::SelectShareTargetResult::kInvalidShareTarget,
/*token=*/base::nullopt, mojo::NullRemote());
return;
}
select_share_target_callback_ = std::move(callback);
// TODO(crbug.com/1099710): Call correct method and pass attachments.
nearby_sharing_service_->SendText(
iter->second, "Example Text",
base::BindOnce(&NearbyPerSessionDiscoveryManager::OnSend,
weak_ptr_factory_.GetWeakPtr()));
}
void NearbyPerSessionDiscoveryManager::OnSend(
NearbySharingService::StatusCodes status) {
DCHECK(select_share_target_callback_);
// If the send call succeeded, we expect OnTransferUpdate() to be called next.
if (status == NearbySharingService::StatusCodes::kOk)
return;
NS_LOG(VERBOSE) << "Failed to select share target";
std::move(select_share_target_callback_)
.Run(nearby_share::mojom::SelectShareTargetResult::kError,
/*token=*/base::nullopt, mojo::NullRemote());
}
// 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_NEARBY_SHARING_NEARBY_PER_SESSION_DISCOVERY_MANAGER_H_
#define CHROME_BROWSER_NEARBY_SHARING_NEARBY_PER_SESSION_DISCOVERY_MANAGER_H_
#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/unguessable_token.h"
#include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
#include "chrome/browser/nearby_sharing/share_target_discovered_callback.h"
#include "chrome/browser/nearby_sharing/transfer_update_callback.h"
#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
// Handles a single nearby device discovery session. Holds all discovered share
// targets for the user to choose from and provides callbacks for when they are
// discovered or lost. All methods are expected to be called on the UI thread
// and there is one instance per WebUI surface.
class NearbyPerSessionDiscoveryManager
: public TransferUpdateCallback,
public ShareTargetDiscoveredCallback,
public nearby_share::mojom::DiscoveryManager {
public:
explicit NearbyPerSessionDiscoveryManager(
NearbySharingService* nearby_sharing_service);
~NearbyPerSessionDiscoveryManager() override;
// TransferUpdateCallback:
void OnTransferUpdate(const ShareTarget& share_target,
const TransferMetadata& transfer_metadata) override;
// ShareTargetDiscoveredCallback:
void OnShareTargetDiscovered(ShareTarget share_target) override;
void OnShareTargetLost(ShareTarget share_target) override;
// nearby_share::mojom::DiscoveryManager:
void StartDiscovery(
mojo::PendingRemote<nearby_share::mojom::ShareTargetListener> listener,
StartDiscoveryCallback callback) override;
void SelectShareTarget(nearby_share::mojom::ShareTargetPtr share_target,
SelectShareTargetCallback callback) override;
private:
// Called as a result of NearbySharingService::Send() to indicate if the
// transfer has been initiated successfully. OnTransferUpdate() will be called
// multiple times as the transfer progresses.
void OnSend(NearbySharingService::StatusCodes status);
NearbySharingService* nearby_sharing_service_;
bool is_registered_ = false;
mojo::Remote<nearby_share::mojom::ShareTargetListener> share_target_listener_;
SelectShareTargetCallback select_share_target_callback_;
// Map of ShareTarget id to discovered ShareTargets.
base::flat_map<base::UnguessableToken, ShareTarget> discovered_share_targets_;
base::WeakPtrFactory<NearbyPerSessionDiscoveryManager> weak_ptr_factory_{
this};
};
#endif // CHROME_BROWSER_NEARBY_SHARING_NEARBY_PER_SESSION_DISCOVERY_MANAGER_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/nearby_sharing/nearby_per_session_discovery_manager.h"
#include "base/test/mock_callback.h"
#include "chrome/browser/nearby_sharing/mock_nearby_sharing_service.h"
#include "chrome/browser/nearby_sharing/share_target.h"
#include "chrome/browser/nearby_sharing/share_target_builder.h"
#include "chrome/browser/nearby_sharing/transfer_metadata.h"
#include "chrome/browser/nearby_sharing/transfer_metadata_builder.h"
#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
using testing::_;
MATCHER_P(MatchesTarget, target, "") {
return arg->id == target.id();
}
class MockShareTargetListener
: public nearby_share::mojom::ShareTargetListener {
public:
MockShareTargetListener() = default;
~MockShareTargetListener() override = default;
mojo::PendingRemote<ShareTargetListener> Bind() {
return receiver_.BindNewPipeAndPassRemote();
}
// nearby_share::mojom::ShareTargetListener:
MOCK_METHOD(void,
OnShareTargetDiscovered,
(nearby_share::mojom::ShareTargetPtr),
(override));
MOCK_METHOD(void,
OnShareTargetLost,
(nearby_share::mojom::ShareTargetPtr),
(override));
private:
mojo::Receiver<ShareTargetListener> receiver_{this};
};
class NearbyPerSessionDiscoveryManagerTest : public testing::Test {
public:
using MockSelectShareTargetCallback = base::MockCallback<
NearbyPerSessionDiscoveryManager::SelectShareTargetCallback>;
using MockStartDiscoveryCallback = base::MockCallback<
NearbyPerSessionDiscoveryManager::StartDiscoveryCallback>;
NearbyPerSessionDiscoveryManagerTest() = default;
~NearbyPerSessionDiscoveryManagerTest() override = default;
MockNearbySharingService& sharing_service() { return sharing_service_; }
NearbyPerSessionDiscoveryManager& manager() { return manager_; }
private:
content::BrowserTaskEnvironment task_environment_;
MockNearbySharingService sharing_service_;
NearbyPerSessionDiscoveryManager manager_{&sharing_service_};
};
} // namespace
TEST_F(NearbyPerSessionDiscoveryManagerTest, CreateDestroyWithoutRegistering) {
EXPECT_CALL(sharing_service(), RegisterSendSurface(&manager(), &manager()))
.Times(0);
EXPECT_CALL(sharing_service(), UnregisterSendSurface(&manager(), &manager()))
.Times(0);
{
NearbyPerSessionDiscoveryManager manager(&sharing_service());
// Creating and destroying an instance should not register itself with the
// NearbySharingService.
}
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, StartDiscovery_Success) {
MockStartDiscoveryCallback callback;
EXPECT_CALL(callback, Run(/*success=*/true));
EXPECT_CALL(sharing_service(), RegisterSendSurface(&manager(), &manager()))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
EXPECT_CALL(sharing_service(), UnregisterSendSurface(&manager(), &manager()))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk));
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), callback.Get());
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, StartDiscovery_Error) {
MockStartDiscoveryCallback callback;
EXPECT_CALL(callback, Run(/*success=*/false));
EXPECT_CALL(sharing_service(), RegisterSendSurface(&manager(), &manager()))
.WillOnce(testing::Return(NearbySharingService::StatusCodes::kError));
EXPECT_CALL(sharing_service(), UnregisterSendSurface(&manager(), &manager()))
.Times(0);
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), callback.Get());
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnShareTargetDiscovered) {
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target = ShareTargetBuilder().build();
base::RunLoop run_loop;
EXPECT_CALL(listener, OnShareTargetDiscovered(MatchesTarget(share_target)))
.WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
manager().OnShareTargetDiscovered(share_target);
run_loop.Run();
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnShareTargetLost) {
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target = ShareTargetBuilder().build();
base::RunLoop run_loop;
EXPECT_CALL(listener, OnShareTargetLost(MatchesTarget(share_target)))
.WillOnce(testing::InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
manager().OnShareTargetLost(share_target);
run_loop.Run();
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_Invalid) {
MockSelectShareTargetCallback callback;
EXPECT_CALL(
callback,
Run(nearby_share::mojom::SelectShareTargetResult::kInvalidShareTarget,
testing::Eq(base::nullopt), testing::IsFalse()));
auto share_target = nearby_share::mojom::ShareTarget::New();
manager().SelectShareTarget(std::move(share_target), callback.Get());
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_SendSuccess) {
// Setup share target
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target = ShareTargetBuilder().build();
manager().OnShareTargetDiscovered(share_target);
// We don't expect the callback to be called until OnTransferUpdate().
MockSelectShareTargetCallback callback;
EXPECT_CALL(callback, Run(_, _, _)).Times(0);
// TODO(crbug.com/1099710): Call correct method and pass attachments.
EXPECT_CALL(sharing_service(), SendText(_, _, _))
.WillOnce(testing::Invoke(
[&share_target](const ShareTarget& target, std::string text,
NearbySharingService::StatusCodesCallback callback) {
EXPECT_EQ(share_target.id(), target.id());
std::move(callback).Run(NearbySharingService::StatusCodes::kOk);
}));
manager().SelectShareTarget(
nearby_share::mojom::ShareTarget::New(share_target.id()), callback.Get());
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_SendError) {
// Setup share target
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target = ShareTargetBuilder().build();
manager().OnShareTargetDiscovered(share_target);
// Expect an error if NearbySharingService::Send*() fails.
MockSelectShareTargetCallback callback;
EXPECT_CALL(callback,
Run(nearby_share::mojom::SelectShareTargetResult::kError,
testing::Eq(base::nullopt), testing::IsFalse()));
// TODO(crbug.com/1099710): Call correct method and pass attachments.
EXPECT_CALL(sharing_service(), SendText(_, _, _))
.WillOnce(testing::Invoke(
[&share_target](const ShareTarget& target, std::string text,
NearbySharingService::StatusCodesCallback callback) {
EXPECT_EQ(share_target.id(), target.id());
std::move(callback).Run(NearbySharingService::StatusCodes::kError);
}));
manager().SelectShareTarget(
nearby_share::mojom::ShareTarget::New(share_target.id()), callback.Get());
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnTransferUpdate_WaitRemote) {
// Setup share target
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target = ShareTargetBuilder().build();
manager().OnShareTargetDiscovered(share_target);
// Expect success without confirmation manager and token.
MockSelectShareTargetCallback callback;
EXPECT_CALL(callback, Run(nearby_share::mojom::SelectShareTargetResult::kOk,
testing::Eq(base::nullopt), testing::IsFalse()));
manager().SelectShareTarget(
nearby_share::mojom::ShareTarget::New(share_target.id()), callback.Get());
auto metadata =
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kAwaitingRemoteAcceptance)
.build();
manager().OnTransferUpdate(share_target, metadata);
}
TEST_F(NearbyPerSessionDiscoveryManagerTest, OnTransferUpdate_WaitLocal) {
// Setup share target
MockShareTargetListener listener;
manager().StartDiscovery(listener.Bind(), base::DoNothing());
ShareTarget share_target = ShareTargetBuilder().build();
manager().OnShareTargetDiscovered(share_target);
std::string token = "Test Token";
// Expect to get a valid confirmation manager remote and token.
MockSelectShareTargetCallback callback;
EXPECT_CALL(callback, Run(nearby_share::mojom::SelectShareTargetResult::kOk,
testing::Eq(token), testing::IsTrue()));
manager().SelectShareTarget(
nearby_share::mojom::ShareTarget::New(share_target.id()), callback.Get());
auto metadata =
TransferMetadataBuilder()
.set_status(TransferMetadata::Status::kAwaitingLocalConfirmation)
.set_token(token)
.build();
manager().OnTransferUpdate(share_target, metadata);
}
...@@ -5,16 +5,17 @@ ...@@ -5,16 +5,17 @@
#ifndef CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_ #ifndef CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_
#define CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_ #define CHROME_BROWSER_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_
#include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "base/containers/flat_map.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/unguessable_token.h"
#include "chrome/browser/nearby_sharing/common/nearby_share_enums.h" #include "chrome/browser/nearby_sharing/common/nearby_share_enums.h"
#include "chrome/browser/nearby_sharing/incoming_share_target_info.h" #include "chrome/browser/nearby_sharing/incoming_share_target_info.h"
#include "chrome/browser/nearby_sharing/nearby_connections_manager.h" #include "chrome/browser/nearby_sharing/nearby_connections_manager.h"
...@@ -140,11 +141,13 @@ class NearbySharingServiceImpl ...@@ -140,11 +141,13 @@ class NearbySharingServiceImpl
// A map of ShareTarget id to IncomingShareTargetInfo. This lets us know which // A map of ShareTarget id to IncomingShareTargetInfo. This lets us know which
// Nearby Connections endpoint and public certificate are related to the // Nearby Connections endpoint and public certificate are related to the
// incoming share target. // incoming share target.
std::map<int, IncomingShareTargetInfo> incoming_share_target_info_map_; base::flat_map<base::UnguessableToken, IncomingShareTargetInfo>
incoming_share_target_info_map_;
// A map of ShareTarget id to OutgoingShareTargetInfo. This lets us know which // A map of ShareTarget id to OutgoingShareTargetInfo. This lets us know which
// endpoint and public certificate are related to the outgoing share target. // endpoint and public certificate are related to the outgoing share target.
// TODO(crbug/1085068) update this map when handling payloads // TODO(crbug/1085068) update this map when handling payloads
std::map<int, OutgoingShareTargetInfo> outgoing_share_target_info_map_; base::flat_map<base::UnguessableToken, OutgoingShareTargetInfo>
outgoing_share_target_info_map_;
// The current advertising power level. PowerLevel::kUnknown while not // The current advertising power level. PowerLevel::kUnknown while not
// advertising. // advertising.
......
...@@ -6,15 +6,6 @@ ...@@ -6,15 +6,6 @@
#include <utility> #include <utility>
#include "base/atomic_sequence_num.h"
namespace {
// The last ID given to the previously created ShareTarget.
base::AtomicSequenceNumber g_id_generator;
} // namespace
ShareTarget::ShareTarget(std::string device_name, ShareTarget::ShareTarget(std::string device_name,
GURL image_url, GURL image_url,
Type type, Type type,
...@@ -23,7 +14,7 @@ ShareTarget::ShareTarget(std::string device_name, ...@@ -23,7 +14,7 @@ ShareTarget::ShareTarget(std::string device_name,
bool is_incoming, bool is_incoming,
base::Optional<std::string> full_name, base::Optional<std::string> full_name,
bool is_known) bool is_known)
: id_(g_id_generator.GetNext()), : id_(base::UnguessableToken::Create()),
device_name_(std::move(device_name)), device_name_(std::move(device_name)),
image_url_(std::move(image_url)), image_url_(std::move(image_url)),
type_(type), type_(type),
...@@ -33,6 +24,12 @@ ShareTarget::ShareTarget(std::string device_name, ...@@ -33,6 +24,12 @@ ShareTarget::ShareTarget(std::string device_name,
full_name_(std::move(full_name)), full_name_(std::move(full_name)),
is_known_(is_known) {} is_known_(is_known) {}
ShareTarget::~ShareTarget() = default;
ShareTarget::ShareTarget(const ShareTarget&) = default; ShareTarget::ShareTarget(const ShareTarget&) = default;
ShareTarget::ShareTarget(ShareTarget&&) = default;
ShareTarget& ShareTarget::operator=(const ShareTarget&) = default; ShareTarget& ShareTarget::operator=(const ShareTarget&) = default;
ShareTarget& ShareTarget::operator=(ShareTarget&&) = default;
ShareTarget::~ShareTarget() = default;
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "base/optional.h" #include "base/optional.h"
#include "base/unguessable_token.h"
#include "chrome/browser/nearby_sharing/file_attachment.h" #include "chrome/browser/nearby_sharing/file_attachment.h"
#include "chrome/browser/nearby_sharing/text_attachment.h" #include "chrome/browser/nearby_sharing/text_attachment.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -26,11 +27,13 @@ class ShareTarget { ...@@ -26,11 +27,13 @@ class ShareTarget {
bool is_incoming, bool is_incoming,
base::Optional<std::string> full_name, base::Optional<std::string> full_name,
bool is_known); bool is_known);
~ShareTarget();
ShareTarget(const ShareTarget&); ShareTarget(const ShareTarget&);
ShareTarget(ShareTarget&&);
ShareTarget& operator=(const ShareTarget&); ShareTarget& operator=(const ShareTarget&);
ShareTarget& operator=(ShareTarget&&);
~ShareTarget();
int id() const { return id_; } base::UnguessableToken id() const { return id_; }
const std::string& device_name() const { return device_name_; } const std::string& device_name() const { return device_name_; }
// Returns a Uri that points to an image of the ShareTarget, if one exists. // Returns a Uri that points to an image of the ShareTarget, if one exists.
...@@ -51,7 +54,7 @@ class ShareTarget { ...@@ -51,7 +54,7 @@ class ShareTarget {
bool is_known() const { return is_known_; } bool is_known() const { return is_known_; }
private: private:
int id_; base::UnguessableToken id_;
std::string device_name_; std::string device_name_;
base::Optional<GURL> image_url_; base::Optional<GURL> image_url_;
Type type_; Type type_;
......
// 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/nearby_sharing/share_target_builder.h"
ShareTargetBuilder::ShareTargetBuilder() = default;
ShareTargetBuilder::~ShareTargetBuilder() = default;
ShareTargetBuilder& ShareTargetBuilder::set_device_name(
const std::string& device_name) {
device_name_ = device_name;
return *this;
}
ShareTargetBuilder& ShareTargetBuilder::set_is_incoming(bool is_incoming) {
is_incoming_ = is_incoming;
return *this;
}
ShareTargetBuilder& ShareTargetBuilder::add_attachment(
TextAttachment attachment) {
text_attachments_.push_back(std::move(attachment));
return *this;
}
ShareTargetBuilder& ShareTargetBuilder::add_attachment(
FileAttachment attachment) {
file_attachments_.push_back(std::move(attachment));
return *this;
}
ShareTarget ShareTargetBuilder::build() const {
return ShareTarget(device_name_,
/*image_url=*/GURL(), ShareTarget::Type::kPhone,
text_attachments_, file_attachments_, is_incoming_,
/*full_name=*/base::nullopt,
/*is_known=*/false);
}
// 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_NEARBY_SHARING_SHARE_TARGET_BUILDER_H_
#define CHROME_BROWSER_NEARBY_SHARING_SHARE_TARGET_BUILDER_H_
#include <string>
#include <vector>
#include "chrome/browser/nearby_sharing/file_attachment.h"
#include "chrome/browser/nearby_sharing/share_target.h"
#include "chrome/browser/nearby_sharing/text_attachment.h"
class ShareTargetBuilder {
public:
ShareTargetBuilder();
~ShareTargetBuilder();
ShareTargetBuilder& set_device_name(const std::string& device_name);
ShareTargetBuilder& set_is_incoming(bool is_incoming);
ShareTargetBuilder& add_attachment(TextAttachment attachment);
ShareTargetBuilder& add_attachment(FileAttachment attachment);
ShareTarget build() const;
private:
std::string device_name_;
bool is_incoming_ = false;
std::vector<TextAttachment> text_attachments_;
std::vector<FileAttachment> file_attachments_;
};
#endif // CHROME_BROWSER_NEARBY_SHARING_SHARE_TARGET_BUILDER_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/nearby_sharing/transfer_metadata_builder.h"
TransferMetadataBuilder::TransferMetadataBuilder() = default;
TransferMetadataBuilder::~TransferMetadataBuilder() = default;
TransferMetadataBuilder& TransferMetadataBuilder::set_progress(
double progress) {
progress_ = progress;
return *this;
}
TransferMetadataBuilder& TransferMetadataBuilder::set_status(
TransferMetadata::Status status) {
status_ = status;
return *this;
}
TransferMetadataBuilder& TransferMetadataBuilder::set_token(
base::Optional<std::string> token) {
token_ = std::move(token);
return *this;
}
TransferMetadata TransferMetadataBuilder::build() const {
return TransferMetadata(status_, progress_, token_,
/*is_original=*/false,
/*is_final_status=*/false);
}
// 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_NEARBY_SHARING_TRANSFER_METADATA_BUILDER_H_
#define CHROME_BROWSER_NEARBY_SHARING_TRANSFER_METADATA_BUILDER_H_
#include <string>
#include "base/optional.h"
#include "chrome/browser/nearby_sharing/transfer_metadata.h"
class TransferMetadataBuilder {
public:
TransferMetadataBuilder();
~TransferMetadataBuilder();
TransferMetadataBuilder& set_progress(double progress);
TransferMetadataBuilder& set_status(TransferMetadata::Status status);
TransferMetadataBuilder& set_token(base::Optional<std::string> token);
TransferMetadata build() const;
private:
double progress_ = 0;
TransferMetadata::Status status_ = TransferMetadata::Status::kInProgress;
base::Optional<std::string> token_;
};
#endif // CHROME_BROWSER_NEARBY_SHARING_TRANSFER_METADATA_BUILDER_H_
...@@ -233,7 +233,10 @@ if (!is_android) { ...@@ -233,7 +233,10 @@ if (!is_android) {
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
] ]
deps = [ "//chrome/browser/resources/nearby_share:web_components" ] deps = [
"//chrome/browser/resources/nearby_share:web_components",
"//chrome/browser/ui/webui/nearby_share:mojom_js",
]
defines = chrome_grit_defines defines = chrome_grit_defines
outputs = [ outputs = [
......
...@@ -9,6 +9,7 @@ js_type_check("closure_compile") { ...@@ -9,6 +9,7 @@ js_type_check("closure_compile") {
is_polymer3 = true is_polymer3 = true
deps = [ deps = [
":app", ":app",
":discovery_manager",
":nearby_confirmation_page", ":nearby_confirmation_page",
":nearby_device", ":nearby_device",
":nearby_discovery_page", ":nearby_discovery_page",
...@@ -27,10 +28,16 @@ js_library("app") { ...@@ -27,10 +28,16 @@ js_library("app") {
] ]
} }
js_library("discovery_manager") {
deps =
[ "//chrome/browser/ui/webui/nearby_share:mojom_js_library_for_compile" ]
}
js_library("nearby_confirmation_page") { js_library("nearby_confirmation_page") {
deps = [ deps = [
":nearby_preview", ":nearby_preview",
":nearby_progress", ":nearby_progress",
"//chrome/browser/ui/webui/nearby_share:mojom_js_library_for_compile",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/cr_elements/cr_button:cr_button.m", "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
"//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m", "//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m",
...@@ -46,8 +53,10 @@ js_library("nearby_device") { ...@@ -46,8 +53,10 @@ js_library("nearby_device") {
js_library("nearby_discovery_page") { js_library("nearby_discovery_page") {
deps = [ deps = [
":discovery_manager",
":nearby_device", ":nearby_device",
":nearby_preview", ":nearby_preview",
"//chrome/browser/ui/webui/nearby_share:mojom_js_library_for_compile",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/cr_elements/cr_button:cr_button.m", "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
] ]
......
<cr-view-manager id="viewManager"> <cr-view-manager id="viewManager">
<nearby-confirmation-page id="[[Page.CONFIRMATION]]" slot="view"> <nearby-confirmation-page id="[[Page.CONFIRMATION]]" slot="view"
confirmation-manager="[[confirmationManager_]]"
confirmation-token="[[confirmationToken_]]">
</nearby-confirmation-page> </nearby-confirmation-page>
<nearby-discovery-page id="[[Page.DISCOVERY]]" slot="view" class="active"> <nearby-discovery-page id="[[Page.DISCOVERY]]" slot="view" class="active"
confirmation-manager="{{confirmationManager_}}"
confirmation-token="{{confirmationToken_}}">
</nearby-discovery-page> </nearby-discovery-page>
<nearby-onboarding-page id="[[Page.ONBOARDING]]" slot="view"> <nearby-onboarding-page id="[[Page.ONBOARDING]]" slot="view">
</nearby-onboarding-page> </nearby-onboarding-page>
......
...@@ -34,5 +34,39 @@ Polymer({ ...@@ -34,5 +34,39 @@ Polymer({
type: Object, type: Object,
value: Page, value: Page,
}, },
/**
* Set by the nearby-discovery-page component when switching to the
* nearby-confirmation-page.
* @type {?nearbyShare.mojom.ConfirmationManagerInterface}
* @private
*/
confirmationManager_: {
type: Object,
value: null,
},
/**
* Set by the nearby-discovery-page component when switching to the
* nearby-confirmation-page.
* @type {?String}
* @private
*/
confirmationToken_: {
type: String,
value: null,
},
},
listeners: {'change-page': 'onChangePage_'},
/**
* Handler for the change-page event.
* @param {!CustomEvent<!{page: Page}>} event
* @private
*/
onChangePage_(event) {
/** @type {CrViewManagerElement} */ (this.$.viewManager)
.switchView(event.detail.page);
}, },
}); });
// 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.
/**
* @fileoverview Provides methods to get or set an instance of a
* DiscoveryManager which allows interaction with native code.
*/
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js';
import './nearby_share.mojom-lite.js';
/** @type {?nearbyShare.mojom.DiscoveryManagerInterface} */
let discoveryManager = null;
/**
* @param {!nearbyShare.mojom.DiscoveryManagerInterface}
* testDiscoveryManager A test discovery manager.
*/
export function setDiscoveryManagerForTesting(testDiscoveryManager) {
discoveryManager = testDiscoveryManager;
}
/**
* @return {!nearbyShare.mojom.DiscoveryManagerInterface} Discovery manager.
*/
export function getDiscoveryManager() {
if (discoveryManager) {
return discoveryManager;
}
discoveryManager = nearbyShare.mojom.DiscoveryManager.getRemote();
discoveryManager.onConnectionError.addListener(() => discoveryManager = null);
return discoveryManager;
}
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
line-height: 138%; line-height: 138%;
} }
#horizontal-line { #confirmation-token {
border-top: 1px dashed rgba(151, 151, 151, 0.74); border-top: 1px dashed rgba(151, 151, 151, 0.74);
color: rgba(0, 0, 0, 0.4); color: rgba(0, 0, 0, 0.4);
flex-grow: 1; flex-grow: 1;
...@@ -77,7 +77,9 @@ ...@@ -77,7 +77,9 @@
<div id="process-row"> <div id="process-row">
<nearby-preview title="Doggo.jpg"></nearby-preview> <nearby-preview title="Doggo.jpg"></nearby-preview>
<div id="horizontal-line">Secure connection ID: A392</div> <div id="confirmation-token">
Secure connection ID: [[confirmationToken]]
</div>
<nearby-progress device-name="Pixel 2"></nearby-progress> <nearby-progress device-name="Pixel 2"></nearby-progress>
</div> </div>
...@@ -91,10 +93,10 @@ ...@@ -91,10 +93,10 @@
</cr-checkbox> </cr-checkbox>
<div id="actions"> <div id="actions">
<cr-button class="cancel-button"> <cr-button id="cancel-button" class="cancel-button" on-click="onCancelTap_">
Cancel Cancel
</cr-button> </cr-button>
<cr-button class="action-button"> <cr-button id="accept-button" class="action-button" on-click="onAcceptTap_">
Confirm Confirm
</cr-button> </cr-button>
</div> </div>
......
...@@ -10,8 +10,11 @@ ...@@ -10,8 +10,11 @@
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js'; import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js';
import './nearby_preview.js'; import './nearby_preview.js';
import './nearby_progress.js'; import './nearby_progress.js';
import './nearby_share.mojom-lite.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
...@@ -19,4 +22,44 @@ Polymer({ ...@@ -19,4 +22,44 @@ Polymer({
is: 'nearby-confirmation-page', is: 'nearby-confirmation-page',
_template: html`{__html_template__}`, _template: html`{__html_template__}`,
properties: {
/**
* ConfirmationManager interface for the currently selected share target.
* Expected to start as null, then change to a valid object before this
* component is shown.
* @type {?nearbyShare.mojom.ConfirmationManagerInterface}
*/
confirmationManager: {
type: Object,
value: null,
},
/**
* Token to show to the user to confirm the selected share target. Expected
* to start as null, then change to a valid object before this component is
* shown.
* @type {?string}
*/
confirmationToken: {
type: String,
value: null,
},
},
/** @private */
onAcceptTap_() {
this.confirmationManager.accept().then(
result => {
// TODO(knollr): Close dialog as send is now in progress.
});
},
/** @private */
onCancelTap_() {
this.confirmationManager.reject().then(
result => {
// TODO(knollr): Close dialog or go back to device discovery.
});
},
}); });
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
<cr-button class="cancel-button"> <cr-button class="cancel-button">
Cancel Cancel
</cr-button> </cr-button>
<cr-button class="action-button" disabled="disabled"> <cr-button id="next-button" class="action-button" on-click="onNextTap_">
Next Next
</cr-button> </cr-button>
</div> </div>
......
...@@ -8,13 +8,64 @@ ...@@ -8,13 +8,64 @@
*/ */
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js';
import './nearby_device.js'; import './nearby_device.js';
import './nearby_preview.js'; import './nearby_preview.js';
import './nearby_share.mojom-lite.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {getDiscoveryManager} from './discovery_manager.js';
Polymer({ Polymer({
is: 'nearby-discovery-page', is: 'nearby-discovery-page',
_template: html`{__html_template__}`, _template: html`{__html_template__}`,
properties: {
/**
* ConfirmationManager interface for the currently selected share target.
* @type {?nearbyShare.mojom.ConfirmationManagerInterface}
*/
confirmationManager: {
notify: true,
type: Object,
value: null,
},
/**
* Token to show to the user to confirm the selected share target.
* @type {?string}
*/
confirmationToken: {
notify: true,
type: String,
value: null,
},
},
/** @private */
onNextTap_() {
// TODO(knollr): Use the selected device after discovering it.
const shareTarget = {
id: /** @type {!mojoBase.mojom.UnguessableToken} */ ({high: 0, low: 17}),
};
getDiscoveryManager().selectShareTarget(shareTarget).then(response => {
const {result, token, confirmationManager} = response;
if (result !== nearbyShare.mojom.SelectShareTargetResult.kOk) {
// TODO(knollr): Show error.
return;
}
if (confirmationManager) {
this.confirmationManager = confirmationManager;
this.confirmationToken = token;
this.fire('change-page', {page: 'confirmation'});
} else {
// TODO(knollr): Close dialog as send is now in progress.
}
});
},
}); });
...@@ -16,6 +16,13 @@ ...@@ -16,6 +16,13 @@
file="nearby_share_dialog.html" file="nearby_share_dialog.html"
type="BINDATA"/> type="BINDATA"/>
<include name="IDR_NEARBY_SHARE_MOJO_JS"
file="${root_gen_dir}/chrome/browser/ui/webui/nearby_share/nearby_share.mojom-lite.js"
use_base_dir="false" type="BINDATA"/>
<include name="IDR_NEARBY_SHARE_DISCOVERY_MANAGER_JS"
file="discovery_manager.js"
type="BINDATA"/>
<!-- Generated Polymer 3 elements --> <!-- Generated Polymer 3 elements -->
<include name="IDR_NEARBY_SHARE_APP_JS" <include name="IDR_NEARBY_SHARE_APP_JS"
file="${root_gen_dir}/chrome/browser/resources/nearby_share/app.js" file="${root_gen_dir}/chrome/browser/resources/nearby_share/app.js"
......
...@@ -1477,6 +1477,7 @@ static_library("ui") { ...@@ -1477,6 +1477,7 @@ static_library("ui") {
"//chrome/browser/ui/color:mixers", "//chrome/browser/ui/color:mixers",
"//chrome/browser/ui/webui/app_management:mojo_bindings", "//chrome/browser/ui/webui/app_management:mojo_bindings",
"//chrome/browser/ui/webui/internals/web_app:mojo_bindings", "//chrome/browser/ui/webui/internals/web_app:mojo_bindings",
"//chrome/browser/ui/webui/nearby_share:mojom",
"//chrome/common:buildflags", "//chrome/common:buildflags",
"//chrome/common/media_router/mojom:media_router", "//chrome/common/media_router/mojom:media_router",
"//chrome/common/search:generate_chrome_colors_info", "//chrome/common/search:generate_chrome_colors_info",
......
# 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.
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [ "nearby_share.mojom" ]
public_deps = [ "//mojo/public/mojom/base" ]
}
file://chrome/browser/nearby_sharing/OWNERS file://chrome/browser/nearby_sharing/OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
# COMPONENT: UI>Browser>Sharing>Nearby # COMPONENT: UI>Browser>Sharing>Nearby
// 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.
module nearby_share.mojom;
import "mojo/public/mojom/base/unguessable_token.mojom";
// Describes a nearby device that is able to receive data via Nearby Share.
struct ShareTarget {
// Unique identifier during the current discovery session. The same physical
// device might have a different value each time StartDiscovery() is called.
mojo_base.mojom.UnguessableToken id;
};
// Result of selecting a share target.
enum SelectShareTargetResult {
// Successfully selected share target. Transfer will continue from here.
kOk,
// Unknown error while selecting the share target.
kError,
// Could not find the selected share target. It may have been lost in the
// mean time.
kInvalidShareTarget,
};
// Interface to be notified about nearby devices. The same ShareTarget might be
// discovered multiple times but will have the same id during one session. This
// is implemented in UI surfaces and called from the browser process.
interface ShareTargetListener {
// Reports a nearby device found via Nearby Share.
OnShareTargetDiscovered(ShareTarget shareTarget);
// Reports that a previously discovered device is no longer available.
OnShareTargetLost(ShareTarget shareTarget);
};
// Manager interface for nearby device discovery. Implemented on the browser
// process and used by UI surfaces.
interface DiscoveryManager {
// Starts discovering nearby devices. The passed |listener| will be called
// with any discovered devices.
StartDiscovery(pending_remote<ShareTargetListener> listener)
=> (bool success);
// Select a previously discovered |shareTarget| to send data to. If the
// selected target requires an additional confirmation of a shared connection
// id by the user it will return a valid ConfirmationManager interface to be
// used to accept or reject the transfer. |token| will contain the string to
// show to the user in that case.
SelectShareTarget(ShareTarget shareTarget)
=> (SelectShareTargetResult result,
string? token,
pending_remote<ConfirmationManager>? confirmation_manager);
};
// Manager interface for the Nearby Share confirmation screen. Implemented on
// the browser process and used by UI surfaces.
interface ConfirmationManager {
// Accepts a connection to the current Share Target.
Accept() => (bool success);
// Rejects a connection to the current Share Target.
Reject() => (bool success);
};
...@@ -6,6 +6,9 @@ ...@@ -6,6 +6,9 @@
#include <string> #include <string>
#include "chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.h"
#include "chrome/browser/nearby_sharing/nearby_sharing_service.h"
#include "chrome/browser/nearby_sharing/nearby_sharing_service_factory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/webui_util.h" #include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/webui_url_constants.h" #include "chrome/common/webui_url_constants.h"
...@@ -15,6 +18,7 @@ ...@@ -15,6 +18,7 @@
#include "chrome/grit/theme_resources.h" #include "chrome/grit/theme_resources.h"
#include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_data_source.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/base/webui/web_ui_util.h" #include "ui/base/webui/web_ui_util.h"
...@@ -33,6 +37,8 @@ NearbyShareDialogUI::NearbyShareDialogUI(content::WebUI* web_ui) ...@@ -33,6 +37,8 @@ NearbyShareDialogUI::NearbyShareDialogUI(content::WebUI* web_ui)
// Nearby Share is not available to incognito or guest profiles. // Nearby Share is not available to incognito or guest profiles.
DCHECK(profile->IsRegularProfile()); DCHECK(profile->IsRegularProfile());
nearby_service_ = NearbySharingServiceFactory::GetForBrowserContext(profile);
content::WebUIDataSource* html_source = content::WebUIDataSource* html_source =
content::WebUIDataSource::Create(chrome::kChromeUINearbyShareHost); content::WebUIDataSource::Create(chrome::kChromeUINearbyShareHost);
...@@ -42,11 +48,21 @@ NearbyShareDialogUI::NearbyShareDialogUI(content::WebUI* web_ui) ...@@ -42,11 +48,21 @@ NearbyShareDialogUI::NearbyShareDialogUI(content::WebUI* web_ui)
kNearbyShareGeneratedPath, kNearbyShareGeneratedPath,
IDR_NEARBY_SHARE_NEARBY_SHARE_DIALOG_HTML); IDR_NEARBY_SHARE_NEARBY_SHARE_DIALOG_HTML);
html_source->AddResourcePath("nearby_share.mojom-lite.js",
IDR_NEARBY_SHARE_MOJO_JS);
content::WebUIDataSource::Add(profile, html_source); content::WebUIDataSource::Add(profile, html_source);
} }
NearbyShareDialogUI::~NearbyShareDialogUI() = default; NearbyShareDialogUI::~NearbyShareDialogUI() = default;
void NearbyShareDialogUI::BindInterface(
mojo::PendingReceiver<mojom::DiscoveryManager> manager) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<NearbyPerSessionDiscoveryManager>(nearby_service_),
std::move(manager));
}
WEB_UI_CONTROLLER_TYPE_IMPL(NearbyShareDialogUI) WEB_UI_CONTROLLER_TYPE_IMPL(NearbyShareDialogUI)
} // namespace nearby_share } // namespace nearby_share
...@@ -5,8 +5,12 @@ ...@@ -5,8 +5,12 @@
#ifndef CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_ #ifndef CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_
#define CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_ #define CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_
#include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h" #include "ui/webui/mojo_web_ui_controller.h"
class NearbySharingService;
namespace nearby_share { namespace nearby_share {
// The WebUI controller for chrome://nearby. // The WebUI controller for chrome://nearby.
...@@ -17,7 +21,13 @@ class NearbyShareDialogUI : public ui::MojoWebUIController { ...@@ -17,7 +21,13 @@ class NearbyShareDialogUI : public ui::MojoWebUIController {
NearbyShareDialogUI& operator=(const NearbyShareDialogUI&) = delete; NearbyShareDialogUI& operator=(const NearbyShareDialogUI&) = delete;
~NearbyShareDialogUI() override; ~NearbyShareDialogUI() override;
// Instantiates the implementor of the mojom::DiscoveryManager mojo
// interface passing the pending receiver that will be internally bound.
void BindInterface(mojo::PendingReceiver<mojom::DiscoveryManager> manager);
private: private:
NearbySharingService* nearby_service_;
WEB_UI_CONTROLLER_TYPE_DECL(); WEB_UI_CONTROLLER_TYPE_DECL();
}; };
......
...@@ -3653,9 +3653,17 @@ test("unit_tests") { ...@@ -3653,9 +3653,17 @@ test("unit_tests") {
"../browser/nearby_sharing/instantmessaging/receive_messages_express_unittest.cc", "../browser/nearby_sharing/instantmessaging/receive_messages_express_unittest.cc",
"../browser/nearby_sharing/instantmessaging/send_message_express_unittest.cc", "../browser/nearby_sharing/instantmessaging/send_message_express_unittest.cc",
"../browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc", "../browser/nearby_sharing/instantmessaging/stream_parser_unittest.cc",
"../browser/nearby_sharing/mock_nearby_sharing_service.cc",
"../browser/nearby_sharing/mock_nearby_sharing_service.h",
"../browser/nearby_sharing/nearby_confirmation_manager_unittest.cc",
"../browser/nearby_sharing/nearby_notification_manager_unittest.cc", "../browser/nearby_sharing/nearby_notification_manager_unittest.cc",
"../browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc",
"../browser/nearby_sharing/nearby_process_manager_unittest.cc", "../browser/nearby_sharing/nearby_process_manager_unittest.cc",
"../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc", "../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc",
"../browser/nearby_sharing/share_target_builder.cc",
"../browser/nearby_sharing/share_target_builder.h",
"../browser/nearby_sharing/transfer_metadata_builder.cc",
"../browser/nearby_sharing/transfer_metadata_builder.h",
"../browser/nearby_sharing/webrtc_signaling_messenger_unittest.cc", "../browser/nearby_sharing/webrtc_signaling_messenger_unittest.cc",
"../browser/performance_manager/test_support/page_discarding_utils.cc", "../browser/performance_manager/test_support/page_discarding_utils.cc",
"../browser/performance_manager/test_support/page_discarding_utils.h", "../browser/performance_manager/test_support/page_discarding_utils.h",
......
...@@ -12,20 +12,41 @@ js_type_check("closure_compile") { ...@@ -12,20 +12,41 @@ js_type_check("closure_compile") {
"js_module_root=./gen/chrome/test/data/webui/", "js_module_root=./gen/chrome/test/data/webui/",
] ]
deps = [ deps = [
":fake_mojo_interfaces",
":nearby_confirmation_page_test", ":nearby_confirmation_page_test",
":nearby_device_test", ":nearby_device_test",
":nearby_discovery_page_test",
":nearby_preview_test", ":nearby_preview_test",
":nearby_progress_test", ":nearby_progress_test",
":nearby_share_app_test",
] ]
} }
js_library("fake_mojo_interfaces") {
deps = [
"..:test_browser_proxy.m",
"//chrome/browser/ui/webui/nearby_share:mojom_js_library_for_compile",
]
}
js_library("nearby_confirmation_page_test") {
deps = [
":fake_mojo_interfaces",
"//chrome/browser/resources/nearby_share:nearby_confirmation_page",
]
externs_list = [ "$externs_path/mocha-2.5.js" ]
}
js_library("nearby_device_test") { js_library("nearby_device_test") {
deps = [ "//chrome/browser/resources/nearby_share:nearby_device" ] deps = [ "//chrome/browser/resources/nearby_share:nearby_device" ]
externs_list = [ "$externs_path/mocha-2.5.js" ] externs_list = [ "$externs_path/mocha-2.5.js" ]
} }
js_library("nearby_confirmation_page_test") { js_library("nearby_discovery_page_test") {
deps = [ "//chrome/browser/resources/nearby_share:nearby_confirmation_page" ] deps = [
":fake_mojo_interfaces",
"//chrome/browser/resources/nearby_share:nearby_discovery_page",
]
externs_list = [ "$externs_path/mocha-2.5.js" ] externs_list = [ "$externs_path/mocha-2.5.js" ]
} }
...@@ -38,3 +59,8 @@ js_library("nearby_progress_test") { ...@@ -38,3 +59,8 @@ js_library("nearby_progress_test") {
deps = [ "//chrome/browser/resources/nearby_share:nearby_progress" ] deps = [ "//chrome/browser/resources/nearby_share:nearby_progress" ]
externs_list = [ "$externs_path/mocha-2.5.js" ] externs_list = [ "$externs_path/mocha-2.5.js" ]
} }
js_library("nearby_share_app_test") {
deps = [ "//chrome/browser/resources/nearby_share:app" ]
externs_list = [ "$externs_path/mocha-2.5.js" ]
}
// 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.
/** @fileoverview Contains fake implementations of mojo interfaces. */
import {TestBrowserProxy} from '../test_browser_proxy.m.js';
/**
* @implements {nearbyShare.mojom.ConfirmationManagerInterface}
* @extends {TestBrowserProxy}
*/
export class FakeConfirmationManagerRemote extends TestBrowserProxy {
constructor() {
super([
'accept',
'reject',
]);
}
async accept() {
this.methodCalled('accept');
return {success: true};
}
async reject() {
this.methodCalled('reject');
return {success: true};
}
}
/**
* @implements {nearbyShare.mojom.DiscoveryManagerInterface}
* @extends {TestBrowserProxy}
*/
export class FakeDiscoveryManagerRemote extends TestBrowserProxy {
constructor() {
super([
'selectShareTarget',
'startDiscovery',
]);
this.selectShareTargetResult = {
result: nearbyShare.mojom.SelectShareTargetResult.kOk,
token: null,
confirmationManager: null,
};
}
/**
* @suppress {checkTypes} FakeConfirmationManagerRemote does not extend
* ConfirmationManagerRemote but implements ConfirmationManagerInterface.
*/
async selectShareTarget() {
this.methodCalled('selectShareTarget');
return this.selectShareTargetResult;
}
async startDiscovery(listener) {
this.methodCalled('startDiscovery', listener);
return {success: true};
}
}
...@@ -48,8 +48,10 @@ const NearbyBrowserTest = class extends PolymerTest { ...@@ -48,8 +48,10 @@ const NearbyBrowserTest = class extends PolymerTest {
[['ConfirmationPage', 'nearby_confirmation_page_test.js'], [['ConfirmationPage', 'nearby_confirmation_page_test.js'],
['Device', 'nearby_device_test.js'], ['Device', 'nearby_device_test.js'],
['DiscoveryPage', 'nearby_discovery_page_test.js'],
['Preview', 'nearby_preview_test.js'], ['Preview', 'nearby_preview_test.js'],
['Progress', 'nearby_progress_test.js'], ['Progress', 'nearby_progress_test.js'],
['ShareApp', 'nearby_share_app_test.js'],
].forEach(test => registerTest(...test)); ].forEach(test => registerTest(...test));
function registerTest(testName, module, caseName) { function registerTest(testName, module, caseName) {
......
...@@ -7,7 +7,8 @@ import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js'; ...@@ -7,7 +7,8 @@ import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://nearby/nearby_confirmation_page.js'; import 'chrome://nearby/nearby_confirmation_page.js';
import {assertEquals} from '../chai_assert.js'; import {assertEquals, assertTrue} from '../chai_assert.js';
import {FakeConfirmationManagerRemote} from './fake_mojo_interfaces.js';
suite('ConfirmatonPageTest', function() { suite('ConfirmatonPageTest', function() {
/** @type {!NearbyConfirmationPageElement} */ /** @type {!NearbyConfirmationPageElement} */
...@@ -26,4 +27,26 @@ suite('ConfirmatonPageTest', function() { ...@@ -26,4 +27,26 @@ suite('ConfirmatonPageTest', function() {
test('renders component', function() { test('renders component', function() {
assertEquals('NEARBY-CONFIRMATION-PAGE', confirmationPageElement.tagName); assertEquals('NEARBY-CONFIRMATION-PAGE', confirmationPageElement.tagName);
}); });
test('calls accept on click', async function() {
const confirmationManager = new FakeConfirmationManagerRemote();
confirmationPageElement.confirmationManager = confirmationManager;
confirmationPageElement.$$('#accept-button').click();
await confirmationManager.whenCalled('accept');
});
test('calls reject on click', async function() {
const confirmationManager = new FakeConfirmationManagerRemote();
confirmationPageElement.confirmationManager = confirmationManager;
confirmationPageElement.$$('#cancel-button').click();
await confirmationManager.whenCalled('reject');
});
test('renders confirmation token', function() {
const token = 'TestToken1234';
confirmationPageElement.confirmationToken = token;
const renderedToken =
confirmationPageElement.$$('#confirmation-token').textContent;
assertTrue(renderedToken.includes(token));
});
}); });
// 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.
// So that mojo is defined.
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://nearby/nearby_discovery_page.js';
import {setDiscoveryManagerForTesting} from 'chrome://nearby/discovery_manager.js';
import {assertEquals} from '../chai_assert.js';
import {FakeConfirmationManagerRemote, FakeDiscoveryManagerRemote} from './fake_mojo_interfaces.js';
suite('DiscoveryPageTest', function() {
/** @type {!NearbyDiscoveryPageElement} */
let discoveryPageElement;
setup(function() {
discoveryPageElement = /** @type {!NearbyDiscoveryPageElement} */ (
document.createElement('nearby-discovery-page'));
document.body.appendChild(discoveryPageElement);
});
teardown(function() {
discoveryPageElement.remove();
});
test('renders component', function() {
assertEquals('NEARBY-DISCOVERY-PAGE', discoveryPageElement.tagName);
});
test('selects share target with success', async function() {
const manager = new FakeDiscoveryManagerRemote();
setDiscoveryManagerForTesting(manager);
discoveryPageElement.$$('#next-button').click();
await manager.whenCalled('selectShareTarget');
});
test('selects share target with error', async function() {
const manager = new FakeDiscoveryManagerRemote();
manager.selectShareTargetResult.result =
nearbyShare.mojom.SelectShareTargetResult.kError;
setDiscoveryManagerForTesting(manager);
discoveryPageElement.$$('#next-button').click();
await manager.whenCalled('selectShareTarget');
});
test('selects share target with confirmation', async function() {
const manager = new FakeDiscoveryManagerRemote();
manager.selectShareTargetResult.token = 'test token';
manager.selectShareTargetResult.confirmationManager =
new FakeConfirmationManagerRemote();
setDiscoveryManagerForTesting(manager);
let eventDetail = null;
discoveryPageElement.addEventListener('change-page', (event) => {
eventDetail = event.detail;
});
discoveryPageElement.$$('#next-button').click();
await manager.whenCalled('selectShareTarget');
assertEquals('confirmation', eventDetail.page);
});
});
// 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.
// So that mojo is defined.
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://nearby/app.js';
import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
suite('ShareAppTest', function() {
/** @type {!NearbyShareAppElement} */
let shareAppElement;
/** @param {!string} page Page to check if it is active. */
function isPageActive(page) {
return shareAppElement.$$(`nearby-${page}-page`)
.classList.contains('active');
}
setup(function() {
shareAppElement = /** @type {!NearbyShareAppElement} */ (
document.createElement('nearby-share-app'));
document.body.appendChild(shareAppElement);
});
teardown(function() {
shareAppElement.remove();
});
test('renders component', function() {
assertEquals('NEARBY-SHARE-APP', shareAppElement.tagName);
});
test('renders nearby-discovery-page by default', function() {
assertTrue(isPageActive('discovery'));
});
test('changes page on event', function() {
// Discovery page should be active by default, other pages should not.
assertTrue(isPageActive('discovery'));
assertFalse(isPageActive('onboarding'));
shareAppElement.fire('change-page', {page: 'onboarding'});
// Onboarding page should now be active, other pages should not.
assertTrue(isPageActive('onboarding'));
assertFalse(isPageActive('discovery'));
});
});
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