| // 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 <utility> |
| |
| #include "base/memory/ptr_util.h" |
| #include "components/arc/arc_bridge_service.h" |
| #include "components/arc/common/intent_helper.mojom.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace arc { |
| |
| namespace { |
| |
| IntentFilter GetIntentFilter(const std::string& host) { |
| std::vector<IntentFilter::AuthorityEntry> authorities; |
| authorities.emplace_back(host, -1); |
| return IntentFilter(std::move(authorities), |
| std::vector<IntentFilter::PatternMatcher>()); |
| } |
| |
| } // namespace |
| |
| class ArcIntentHelperTest : public testing::Test { |
| protected: |
| ArcIntentHelperTest() = default; |
| |
| class TestOpenUrlDelegate : public ArcIntentHelperBridge::OpenUrlDelegate { |
| public: |
| ~TestOpenUrlDelegate() override = default; |
| |
| // ArcIntentHelperBridge::OpenUrlDelegate: |
| void OpenUrl(const GURL& url) override { last_opened_url_ = url; } |
| |
| GURL TakeLastOpenedUrl() { |
| GURL result = std::move(last_opened_url_); |
| last_opened_url_ = GURL(); |
| return result; |
| } |
| |
| private: |
| GURL last_opened_url_; |
| }; |
| |
| std::unique_ptr<ArcBridgeService> arc_bridge_service_; |
| TestOpenUrlDelegate* test_open_url_delegate_; // owned by |instance_| |
| std::unique_ptr<ArcIntentHelperBridge> instance_; |
| |
| private: |
| void SetUp() override { |
| arc_bridge_service_ = std::make_unique<ArcBridgeService>(); |
| instance_ = std::make_unique<ArcIntentHelperBridge>( |
| nullptr /* context */, arc_bridge_service_.get()); |
| test_open_url_delegate_ = new TestOpenUrlDelegate(); |
| instance_->SetOpenUrlDelegateForTesting( |
| base::WrapUnique(test_open_url_delegate_)); |
| } |
| |
| void TearDown() override { |
| instance_.reset(); |
| arc_bridge_service_.reset(); |
| } |
| |
| DISALLOW_COPY_AND_ASSIGN(ArcIntentHelperTest); |
| }; |
| |
| // Tests if IsIntentHelperPackage works as expected. Probably too trivial |
| // to test but just in case. |
| TEST_F(ArcIntentHelperTest, TestIsIntentHelperPackage) { |
| EXPECT_FALSE(ArcIntentHelperBridge::IsIntentHelperPackage("")); |
| EXPECT_FALSE(ArcIntentHelperBridge::IsIntentHelperPackage( |
| ArcIntentHelperBridge::kArcIntentHelperPackageName + std::string("a"))); |
| EXPECT_FALSE(ArcIntentHelperBridge::IsIntentHelperPackage( |
| ArcIntentHelperBridge::kArcIntentHelperPackageName + |
| std::string("/.ArcIntentHelperActivity"))); |
| EXPECT_TRUE(ArcIntentHelperBridge::IsIntentHelperPackage( |
| ArcIntentHelperBridge::kArcIntentHelperPackageName)); |
| } |
| |
| // 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 = ArcIntentHelperBridge::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 = ArcIntentHelperBridge::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 = ArcIntentHelperBridge::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 = ArcIntentHelperBridge::kArcIntentHelperPackageName; |
| orig.push_back(mojom::IntentHandlerInfo::New()); |
| orig[1]->name = "1"; |
| orig[1]->package_name = ArcIntentHelperBridge::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 FakeObserver : public ArcIntentHelperObserver { |
| public: |
| FakeObserver() = default; |
| void OnIntentFiltersUpdated() override { updated_ = true; } |
| bool IsUpdated() { return updated_; } |
| void Reset() { updated_ = false; } |
| |
| private: |
| bool updated_ = false; |
| }; |
| |
| // Observer should be called when intent filter is updated. |
| auto observer = std::make_unique<FakeObserver>(); |
| instance_->AddObserver(observer.get()); |
| EXPECT_FALSE(observer->IsUpdated()); |
| instance_->OnIntentFiltersUpdated(std::vector<IntentFilter>()); |
| EXPECT_TRUE(observer->IsUpdated()); |
| |
| // Observer should not be called after it's removed. |
| observer->Reset(); |
| instance_->RemoveObserver(observer.get()); |
| instance_->OnIntentFiltersUpdated(std::vector<IntentFilter>()); |
| EXPECT_FALSE(observer->IsUpdated()); |
| } |
| |
| // Tests that ShouldChromeHandleUrl returns true by default. |
| TEST_F(ArcIntentHelperTest, TestDefault) { |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("http://www.google.com"))); |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("https://www.google.com"))); |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("file:///etc/password"))); |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("chrome://help"))); |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("about://chrome"))); |
| } |
| |
| // Tests that ShouldChromeHandleUrl returns false when there's a match. |
| TEST_F(ArcIntentHelperTest, TestSingleFilter) { |
| std::vector<IntentFilter> array; |
| array.emplace_back(GetIntentFilter("www.google.com")); |
| instance_->OnIntentFiltersUpdated(std::move(array)); |
| |
| EXPECT_FALSE(instance_->ShouldChromeHandleUrl(GURL("http://www.google.com"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("https://www.google.com"))); |
| |
| EXPECT_TRUE( |
| instance_->ShouldChromeHandleUrl(GURL("https://www.google.co.uk"))); |
| } |
| |
| // Tests the same with multiple filters. |
| TEST_F(ArcIntentHelperTest, TestMultipleFilters) { |
| std::vector<IntentFilter> array; |
| array.emplace_back(GetIntentFilter("www.google.com")); |
| array.emplace_back(GetIntentFilter("www.google.co.uk")); |
| array.emplace_back(GetIntentFilter("dev.chromium.org")); |
| instance_->OnIntentFiltersUpdated(std::move(array)); |
| |
| EXPECT_FALSE(instance_->ShouldChromeHandleUrl(GURL("http://www.google.com"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("https://www.google.com"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("http://www.google.co.uk"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("https://www.google.co.uk"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("http://dev.chromium.org"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("https://dev.chromium.org"))); |
| |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("http://www.android.com"))); |
| } |
| |
| // Tests that ShouldChromeHandleUrl returns true for non http(s) URLs. |
| TEST_F(ArcIntentHelperTest, TestNonHttp) { |
| std::vector<IntentFilter> array; |
| array.emplace_back(GetIntentFilter("www.google.com")); |
| instance_->OnIntentFiltersUpdated(std::move(array)); |
| |
| EXPECT_TRUE( |
| instance_->ShouldChromeHandleUrl(GURL("chrome://www.google.com"))); |
| EXPECT_TRUE( |
| instance_->ShouldChromeHandleUrl(GURL("custom://www.google.com"))); |
| } |
| |
| // Tests that ShouldChromeHandleUrl discards the previous filters when |
| // UpdateIntentFilters is called with new ones. |
| TEST_F(ArcIntentHelperTest, TestMultipleUpdate) { |
| std::vector<IntentFilter> array; |
| array.emplace_back(GetIntentFilter("www.google.com")); |
| array.emplace_back(GetIntentFilter("dev.chromium.org")); |
| instance_->OnIntentFiltersUpdated(std::move(array)); |
| |
| std::vector<IntentFilter> array2; |
| array2.emplace_back(GetIntentFilter("www.google.co.uk")); |
| array2.emplace_back(GetIntentFilter("dev.chromium.org")); |
| array2.emplace_back(GetIntentFilter("www.android.com")); |
| instance_->OnIntentFiltersUpdated(std::move(array2)); |
| |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("http://www.google.com"))); |
| EXPECT_TRUE(instance_->ShouldChromeHandleUrl(GURL("https://www.google.com"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("http://www.google.co.uk"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("https://www.google.co.uk"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("http://dev.chromium.org"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("https://dev.chromium.org"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("http://www.android.com"))); |
| EXPECT_FALSE( |
| instance_->ShouldChromeHandleUrl(GURL("https://www.android.com"))); |
| } |
| |
| // 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 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://help"); |
| EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("chrome://version"); |
| EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:"); // this redirects to chrome://version |
| EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| // Some of the about/chrome URLs are whitelisted (for now). |
| instance_->OnOpenUrl("about:blank"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:downloads"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:history"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:settings"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:settings/accounts"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:settings/keyboard-overlay"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:settings/networks?type=VPN"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:settings/networks?type=this_is_not_whitelisted"); |
| EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:settings/syncSetup"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("about:settings/thisIsNotWhitelisted"); |
| EXPECT_FALSE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| |
| instance_->OnOpenUrl("chrome://settings"); |
| EXPECT_TRUE(test_open_url_delegate_->TakeLastOpenedUrl().is_valid()); |
| } |
| |
| // Tests that OnOpenChromeSettings opens the specified settings section in the |
| // Chrome browser. |
| TEST_F(ArcIntentHelperTest, TestOnOpenChromeSettings) { |
| instance_->OnOpenChromeSettings(mojom::SettingsPage::MAIN); |
| EXPECT_EQ(GURL("chrome://settings"), |
| test_open_url_delegate_->TakeLastOpenedUrl()); |
| |
| instance_->OnOpenChromeSettings(mojom::SettingsPage::MULTIDEVICE); |
| EXPECT_EQ(GURL("chrome://settings/multidevice"), |
| test_open_url_delegate_->TakeLastOpenedUrl()); |
| |
| instance_->OnOpenChromeSettings(mojom::SettingsPage::WIFI); |
| EXPECT_EQ(GURL("chrome://settings/networks/?type=WiFi"), |
| test_open_url_delegate_->TakeLastOpenedUrl()); |
| } |
| |
| // Tests that AppendStringToIntentHelperPackageName works. |
| TEST_F(ArcIntentHelperTest, TestAppendStringToIntentHelperPackageName) { |
| std::string fake_activity = "this_is_a_fake_activity"; |
| EXPECT_EQ( |
| ArcIntentHelperBridge::AppendStringToIntentHelperPackageName( |
| fake_activity), |
| ArcIntentHelperBridge::kArcIntentHelperPackageName + "." + fake_activity); |
| |
| std::string empty_string = ""; |
| EXPECT_EQ(ArcIntentHelperBridge::AppendStringToIntentHelperPackageName( |
| empty_string), |
| ArcIntentHelperBridge::kArcIntentHelperPackageName + "."); |
| } |
| |
| } // namespace arc |