123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- // Copyright 2016 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 "components/arc/intent_helper/arc_intent_helper_bridge.h"
- #include <memory>
- #include <string>
- #include <utility>
- #include <vector>
- #include "ash/components/arc/mojom/intent_helper.mojom-forward.h"
- #include "ash/components/arc/mojom/intent_helper.mojom-shared.h"
- #include "ash/components/arc/mojom/intent_helper.mojom.h"
- #include "ash/components/arc/session/arc_bridge_service.h"
- #include "base/files/file_path.h"
- #include "base/memory/ptr_util.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "components/arc/common/intent_helper/arc_intent_helper_package.h"
- #include "components/arc/intent_helper/intent_constants.h"
- #include "components/arc/intent_helper/open_url_delegate.h"
- #include "mojo/public/cpp/bindings/clone_traits.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace arc {
- class ArcIntentHelperTest : public testing::Test {
- protected:
- ArcIntentHelperTest() = default;
- ArcIntentHelperTest(const ArcIntentHelperTest&) = delete;
- ArcIntentHelperTest& operator=(const ArcIntentHelperTest&) = delete;
- class TestOpenUrlDelegate : public OpenUrlDelegate {
- public:
- ~TestOpenUrlDelegate() override = default;
- // OpenUrlDelegate:
- void OpenUrlFromArc(const GURL& url) override { last_opened_url_ = url; }
- void OpenWebAppFromArc(const GURL& url) override { last_opened_url_ = url; }
- void OpenArcCustomTab(
- const GURL& url,
- int32_t task_id,
- mojom::IntentHelperHost::OnOpenCustomTabCallback callback) override {
- std::move(callback).Run(mojo::NullRemote());
- }
- void OpenChromePageFromArc(mojom::ChromePage chrome_page) override {}
- void OpenAppWithIntent(const GURL& url,
- mojom::LaunchIntentPtr intent) override {
- last_opened_url_ = url;
- last_opened_intent_ = std::move(intent);
- }
- GURL TakeLastOpenedUrl() {
- GURL result = std::move(last_opened_url_);
- last_opened_url_ = GURL();
- return result;
- }
- mojom::LaunchIntentPtr TakeLastOpenedIntent() {
- auto result = std::move(last_opened_intent_);
- last_opened_intent_.reset();
- return result;
- }
- private:
- GURL last_opened_url_;
- mojom::LaunchIntentPtr last_opened_intent_;
- };
- std::unique_ptr<ArcBridgeService> arc_bridge_service_;
- std::unique_ptr<TestOpenUrlDelegate> test_open_url_delegate_;
- std::unique_ptr<ArcIntentHelperBridge> instance_;
- private:
- void SetUp() override {
- arc_bridge_service_ = std::make_unique<ArcBridgeService>();
- test_open_url_delegate_ = std::make_unique<TestOpenUrlDelegate>();
- instance_ = std::make_unique<ArcIntentHelperBridge>(
- nullptr /* context */, arc_bridge_service_.get());
- ArcIntentHelperBridge::SetOpenUrlDelegate(test_open_url_delegate_.get());
- }
- void TearDown() override {
- ArcIntentHelperBridge::SetOpenUrlDelegate(nullptr);
- instance_.reset();
- test_open_url_delegate_.reset();
- arc_bridge_service_.reset();
- }
- };
- // Tests if FilterOutIntentHelper removes handlers as expected.
- TEST_F(ArcIntentHelperTest, TestFilterOutIntentHelper) {
- {
- std::vector<mojom::IntentHandlerInfoPtr> orig;
- std::vector<mojom::IntentHandlerInfoPtr> filtered =
- ArcIntentHelperBridge::FilterOutIntentHelper(std::move(orig));
- EXPECT_EQ(0U, filtered.size());
- }
- {
- std::vector<mojom::IntentHandlerInfoPtr> orig;
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[0]->name = "0";
- orig[0]->package_name = "package_name0";
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[1]->name = "1";
- orig[1]->package_name = "package_name1";
- // FilterOutIntentHelper is no-op in this case.
- std::vector<mojom::IntentHandlerInfoPtr> filtered =
- ArcIntentHelperBridge::FilterOutIntentHelper(std::move(orig));
- EXPECT_EQ(2U, filtered.size());
- }
- {
- std::vector<mojom::IntentHandlerInfoPtr> orig;
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[0]->name = "0";
- orig[0]->package_name = kArcIntentHelperPackageName;
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[1]->name = "1";
- orig[1]->package_name = "package_name1";
- // FilterOutIntentHelper should remove the first element.
- std::vector<mojom::IntentHandlerInfoPtr> filtered =
- ArcIntentHelperBridge::FilterOutIntentHelper(std::move(orig));
- ASSERT_EQ(1U, filtered.size());
- EXPECT_EQ("1", filtered[0]->name);
- EXPECT_EQ("package_name1", filtered[0]->package_name);
- }
- {
- std::vector<mojom::IntentHandlerInfoPtr> orig;
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[0]->name = "0";
- orig[0]->package_name = kArcIntentHelperPackageName;
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[1]->name = "1";
- orig[1]->package_name = "package_name1";
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[2]->name = "2";
- orig[2]->package_name = kArcIntentHelperPackageName;
- // FilterOutIntentHelper should remove two elements.
- std::vector<mojom::IntentHandlerInfoPtr> filtered =
- ArcIntentHelperBridge::FilterOutIntentHelper(std::move(orig));
- ASSERT_EQ(1U, filtered.size());
- EXPECT_EQ("1", filtered[0]->name);
- EXPECT_EQ("package_name1", filtered[0]->package_name);
- }
- {
- std::vector<mojom::IntentHandlerInfoPtr> orig;
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[0]->name = "0";
- orig[0]->package_name = kArcIntentHelperPackageName;
- orig.push_back(mojom::IntentHandlerInfo::New());
- orig[1]->name = "1";
- orig[1]->package_name = kArcIntentHelperPackageName;
- // FilterOutIntentHelper should remove all elements.
- std::vector<mojom::IntentHandlerInfoPtr> filtered =
- ArcIntentHelperBridge::FilterOutIntentHelper(std::move(orig));
- EXPECT_EQ(0U, filtered.size());
- }
- }
- // Tests if observer works as expected.
- TEST_F(ArcIntentHelperTest, TestObserver) {
- class MockObserver : public ArcIntentHelperObserver {
- public:
- MOCK_METHOD(void,
- OnArcDownloadAdded,
- (const base::FilePath& relative_path,
- const std::string& owner_package_name),
- (override));
- MOCK_METHOD(void,
- OnIntentFiltersUpdated,
- (const absl::optional<std::string>& package_name),
- (override));
- MOCK_METHOD(
- void,
- OnArcSupportedLinksChanged,
- (const std::vector<arc::mojom::SupportedLinksPtr>& added_packages,
- const std::vector<arc::mojom::SupportedLinksPtr>& removed_packages,
- arc::mojom::SupportedLinkChangeSource source),
- (override));
- };
- // Create and add observer.
- testing::StrictMock<MockObserver> observer;
- instance_->AddObserver(&observer);
- {
- // Observer should be called when a download is added.
- std::string relative_path("Download/foo/bar.pdf");
- std::string owner_package_name("owner_package_name");
- EXPECT_CALL(observer,
- OnArcDownloadAdded(testing::Eq(base::FilePath(relative_path)),
- testing::Ref(owner_package_name)));
- instance_->OnDownloadAdded(relative_path, owner_package_name);
- testing::Mock::VerifyAndClearExpectations(&observer);
- }
- {
- // Observer should *not* be called when a download is added outside of the
- // Download/ folder. This would be an unexpected event coming from ARC but
- // we protect against it because ARC is treated as an untrusted source.
- instance_->OnDownloadAdded(/*relative_path=*/"Download/../foo/bar.pdf",
- /*owner_package_name=*/"owner_package_name");
- testing::Mock::VerifyAndClearExpectations(&observer);
- }
- {
- // Observer should be called when an intent filter is updated.
- EXPECT_CALL(observer, OnIntentFiltersUpdated(testing::Eq(absl::nullopt)));
- instance_->OnIntentFiltersUpdated(/*filters=*/std::vector<IntentFilter>());
- testing::Mock::VerifyAndClearExpectations(&observer);
- }
- {
- // Observer should be called when supported links change.
- EXPECT_CALL(observer, OnArcSupportedLinksChanged);
- instance_->OnSupportedLinksChanged(
- /*added_packages=*/{},
- /*removed_packages=*/{},
- arc::mojom::SupportedLinkChangeSource::kArcSystem);
- testing::Mock::VerifyAndClearExpectations(&observer);
- }
- // Observer should not be called after it's removed.
- instance_->RemoveObserver(&observer);
- instance_->OnDownloadAdded(/*relative_path=*/"Download/foo/bar.pdf",
- /*owner_package_name=*/"owner_package_name");
- instance_->OnIntentFiltersUpdated(/*filters=*/{});
- instance_->OnSupportedLinksChanged(
- /*added_packages=*/{},
- /*removed_packages=*/{},
- arc::mojom::SupportedLinkChangeSource::kArcSystem);
- }
- // Tests that OnOpenUrl opens the URL in Chrome browser.
- TEST_F(ArcIntentHelperTest, TestOnOpenUrl) {
- instance_->OnOpenUrl("http://google.com");
- EXPECT_EQ(GURL("http://google.com"),
- test_open_url_delegate_->TakeLastOpenedUrl());
- instance_->OnOpenUrl("https://google.com");
- EXPECT_EQ(GURL("https://google.com"),
- test_open_url_delegate_->TakeLastOpenedUrl());
- }
- // Tests that OnOpenWebApp opens only HTTPS URLs or localhost.
- TEST_F(ArcIntentHelperTest, TestOnOpenWebApp) {
- instance_->OnOpenWebApp("http://google.com");
- EXPECT_EQ(GURL(), test_open_url_delegate_->TakeLastOpenedUrl());
- instance_->OnOpenWebApp("http://localhost/");
- EXPECT_EQ(GURL("http://localhost/"),
- test_open_url_delegate_->TakeLastOpenedUrl());
- instance_->OnOpenWebApp("https://google.com");
- EXPECT_EQ(GURL("https://google.com"),
- test_open_url_delegate_->TakeLastOpenedUrl());
- }
- // Tests that OnOpenUrl does not open URLs with the 'chrome://' and equivalent
- // schemes like 'about:'.
- TEST_F(ArcIntentHelperTest, TestOnOpenUrl_ChromeScheme) {
- instance_->OnOpenUrl("chrome://www.google.com");
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- instance_->OnOpenUrl("chrome://settings");
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- instance_->OnOpenUrl("about:");
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- instance_->OnOpenUrl("about:settings");
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- instance_->OnOpenUrl("about:blank");
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- }
- // Tests that OnOpenAppWithIntents opens only HTTPS URLs.
- TEST_F(ArcIntentHelperTest, TestOnOpenAppWithIntent) {
- base::HistogramTester histograms;
- auto intent = mojom::LaunchIntent::New();
- intent->action = arc::kIntentActionSend;
- intent->extra_text = "Foo";
- instance_->OnOpenAppWithIntent(GURL("https://www.google.com"),
- std::move(intent));
- EXPECT_EQ(GURL("https://www.google.com"),
- test_open_url_delegate_->TakeLastOpenedUrl());
- EXPECT_EQ("Foo", test_open_url_delegate_->TakeLastOpenedIntent()->extra_text);
- histograms.ExpectBucketCount("Arc.IntentHelper.OpenAppWithIntentAction",
- 2 /* OpenIntentAction::kSend */, 1);
- instance_->OnOpenAppWithIntent(GURL("http://www.google.com"),
- mojom::LaunchIntent::New());
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedIntent().is_null());
- instance_->OnOpenAppWithIntent(GURL("http://localhost:8000/foo"),
- mojom::LaunchIntent::New());
- EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedIntent().is_null());
- instance_->OnOpenAppWithIntent(GURL("chrome://settings"),
- mojom::LaunchIntent::New());
- EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid());
- EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedIntent().is_null());
- }
- // Tests that AppendStringToIntentHelperPackageName works.
- TEST_F(ArcIntentHelperTest, TestAppendStringToIntentHelperPackageName) {
- std::string package_name = kArcIntentHelperPackageName;
- std::string fake_activity = "this_is_a_fake_activity";
- EXPECT_EQ(ArcIntentHelperBridge::AppendStringToIntentHelperPackageName(
- fake_activity),
- package_name + "." + fake_activity);
- const std::string empty_string;
- EXPECT_EQ(ArcIntentHelperBridge::AppendStringToIntentHelperPackageName(
- empty_string),
- package_name + ".");
- }
- } // namespace arc
|