isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 1 | // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/extensions/extension_tab_util.h" |
| 6 | |
| 7 | #include "base/macros.h" |
Tim Judkins | 495a667 | 2020-05-11 23:08:28 | [diff] [blame] | 8 | #include "chrome/browser/extensions/api/tabs/tabs_constants.h" |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 9 | #include "chrome/common/extensions/api/tabs.h" |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 10 | #include "extensions/common/extension.h" |
| 11 | #include "extensions/common/extension_builder.h" |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 12 | #include "testing/gtest/include/gtest/gtest.h" |
| 13 | |
| 14 | namespace extensions { |
| 15 | |
| 16 | namespace { |
| 17 | |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 18 | class ExtensionTabUtilTestDelegate : public ExtensionTabUtil::Delegate { |
| 19 | public: |
| 20 | ExtensionTabUtilTestDelegate() {} |
Peter Boström | 53c6c595 | 2021-09-17 09:41:26 | [diff] [blame^] | 21 | |
| 22 | ExtensionTabUtilTestDelegate(const ExtensionTabUtilTestDelegate&) = delete; |
| 23 | ExtensionTabUtilTestDelegate& operator=(const ExtensionTabUtilTestDelegate&) = |
| 24 | delete; |
| 25 | |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 26 | ~ExtensionTabUtilTestDelegate() override {} |
| 27 | |
| 28 | // ExtensionTabUtil::Delegate |
Tim Judkins | 92389f75 | 2019-09-20 21:04:14 | [diff] [blame] | 29 | ExtensionTabUtil::ScrubTabBehaviorType GetScrubTabBehavior( |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 30 | const Extension* extension) override { |
| 31 | return ExtensionTabUtil::kScrubTabUrlToOrigin; |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 32 | } |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 33 | }; |
| 34 | |
| 35 | } // namespace |
| 36 | |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 37 | // Test that the custom GetScrubTabBehavior delegate works - in this test it |
| 38 | // always returns kScrubTabUrlToOrigin |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 39 | TEST(ExtensionTabUtilTest, Delegate) { |
Ivan Sandrk | e2b20c6 | 2018-09-10 16:23:53 | [diff] [blame] | 40 | ExtensionTabUtil::SetPlatformDelegate( |
| 41 | std::make_unique<ExtensionTabUtilTestDelegate>()); |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 42 | |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 43 | // Build an extension that passes the permission checks for the generic |
| 44 | // GetScrubTabBehavior |
| 45 | auto extension = ExtensionBuilder("test").AddPermission("tabs").Build(); |
| 46 | |
| 47 | ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = |
John Lee | bfbb37cb | 2019-08-26 22:23:18 | [diff] [blame] | 48 | ExtensionTabUtil::GetScrubTabBehavior( |
| 49 | extension.get(), Feature::Context::UNSPECIFIED_CONTEXT, |
| 50 | GURL("http://www.google.com")); |
Tim Judkins | 92389f75 | 2019-09-20 21:04:14 | [diff] [blame] | 51 | EXPECT_EQ(ExtensionTabUtil::kScrubTabUrlToOrigin, |
| 52 | scrub_tab_behavior.committed_info); |
| 53 | EXPECT_EQ(ExtensionTabUtil::kScrubTabUrlToOrigin, |
| 54 | scrub_tab_behavior.pending_info); |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 55 | |
| 56 | // Unset the delegate. |
| 57 | ExtensionTabUtil::SetPlatformDelegate(nullptr); |
| 58 | } |
| 59 | |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 60 | TEST(ExtensionTabUtilTest, ScrubTabBehaviorForTabsPermission) { |
| 61 | auto extension = ExtensionBuilder("Extension with tabs permission") |
| 62 | .AddPermission("tabs") |
| 63 | .Build(); |
| 64 | ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = |
John Lee | bfbb37cb | 2019-08-26 22:23:18 | [diff] [blame] | 65 | ExtensionTabUtil::GetScrubTabBehavior( |
| 66 | extension.get(), Feature::Context::UNSPECIFIED_CONTEXT, |
| 67 | GURL("http://www.google.com")); |
Tim Judkins | 92389f75 | 2019-09-20 21:04:14 | [diff] [blame] | 68 | EXPECT_EQ(ExtensionTabUtil::kDontScrubTab, scrub_tab_behavior.committed_info); |
| 69 | EXPECT_EQ(ExtensionTabUtil::kDontScrubTab, scrub_tab_behavior.pending_info); |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | TEST(ExtensionTabUtilTest, ScrubTabBehaviorForNoPermission) { |
| 73 | auto extension = ExtensionBuilder("Extension with no permissions").Build(); |
| 74 | ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = |
John Lee | bfbb37cb | 2019-08-26 22:23:18 | [diff] [blame] | 75 | ExtensionTabUtil::GetScrubTabBehavior( |
| 76 | extension.get(), Feature::Context::UNSPECIFIED_CONTEXT, |
| 77 | GURL("http://www.google.com")); |
Tim Judkins | 92389f75 | 2019-09-20 21:04:14 | [diff] [blame] | 78 | EXPECT_EQ(ExtensionTabUtil::kScrubTabFully, |
| 79 | scrub_tab_behavior.committed_info); |
| 80 | EXPECT_EQ(ExtensionTabUtil::kScrubTabFully, scrub_tab_behavior.pending_info); |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | TEST(ExtensionTabUtilTest, ScrubTabBehaviorForHostPermission) { |
| 84 | auto extension = ExtensionBuilder("Extension with host permission") |
| 85 | .AddPermission("*://www.google.com/*") |
| 86 | .Build(); |
| 87 | ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = |
| 88 | ExtensionTabUtil::GetScrubTabBehavior( |
John Lee | bfbb37cb | 2019-08-26 22:23:18 | [diff] [blame] | 89 | extension.get(), Feature::Context::UNSPECIFIED_CONTEXT, |
| 90 | GURL("http://www.google.com/some/path")); |
Tim Judkins | 92389f75 | 2019-09-20 21:04:14 | [diff] [blame] | 91 | EXPECT_EQ(ExtensionTabUtil::kDontScrubTab, scrub_tab_behavior.committed_info); |
| 92 | EXPECT_EQ(ExtensionTabUtil::kDontScrubTab, scrub_tab_behavior.pending_info); |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | TEST(ExtensionTabUtilTest, ScrubTabBehaviorForNoExtension) { |
| 96 | ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = |
John Lee | bfbb37cb | 2019-08-26 22:23:18 | [diff] [blame] | 97 | ExtensionTabUtil::GetScrubTabBehavior( |
| 98 | nullptr, Feature::Context::UNSPECIFIED_CONTEXT, |
| 99 | GURL("http://www.google.com")); |
Tim Judkins | 92389f75 | 2019-09-20 21:04:14 | [diff] [blame] | 100 | EXPECT_EQ(ExtensionTabUtil::kScrubTabFully, |
| 101 | scrub_tab_behavior.committed_info); |
| 102 | EXPECT_EQ(ExtensionTabUtil::kScrubTabFully, scrub_tab_behavior.pending_info); |
John Lee | 76e40a3 | 2019-08-20 17:52:40 | [diff] [blame] | 103 | } |
| 104 | |
John Lee | bfbb37cb | 2019-08-26 22:23:18 | [diff] [blame] | 105 | TEST(ExtensionTabUtilTest, ScrubTabBehaviorForWebUI) { |
| 106 | ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = |
| 107 | ExtensionTabUtil::GetScrubTabBehavior(nullptr, |
| 108 | Feature::Context::WEBUI_CONTEXT, |
| 109 | GURL("http://www.google.com")); |
Tim Judkins | 92389f75 | 2019-09-20 21:04:14 | [diff] [blame] | 110 | EXPECT_EQ(ExtensionTabUtil::kDontScrubTab, scrub_tab_behavior.committed_info); |
| 111 | EXPECT_EQ(ExtensionTabUtil::kDontScrubTab, scrub_tab_behavior.pending_info); |
John Lee | bfbb37cb | 2019-08-26 22:23:18 | [diff] [blame] | 112 | } |
| 113 | |
Giovanni Ortuño Urquidi | 7b65723 | 2020-03-01 12:08:46 | [diff] [blame] | 114 | TEST(ExtensionTabUtilTest, ScrubTabBehaviorForWebUIUntrusted) { |
| 115 | ExtensionTabUtil::ScrubTabBehavior scrub_tab_behavior = |
| 116 | ExtensionTabUtil::GetScrubTabBehavior( |
| 117 | nullptr, Feature::Context::WEBUI_UNTRUSTED_CONTEXT, |
| 118 | GURL("http://www.google.com")); |
| 119 | EXPECT_EQ(ExtensionTabUtil::kScrubTabFully, |
| 120 | scrub_tab_behavior.committed_info); |
| 121 | EXPECT_EQ(ExtensionTabUtil::kScrubTabFully, scrub_tab_behavior.pending_info); |
| 122 | } |
| 123 | |
Joel Hockey | a8ac458 | 2020-04-21 08:10:58 | [diff] [blame] | 124 | TEST(ExtensionTabUtilTest, ResolvePossiblyRelativeURL) { |
| 125 | auto extension = ExtensionBuilder("test").Build(); |
| 126 | EXPECT_EQ(ExtensionTabUtil::ResolvePossiblyRelativeURL( |
| 127 | "http://example.com/path", extension.get()), |
| 128 | GURL("http://example.com/path")); |
| 129 | EXPECT_EQ( |
| 130 | ExtensionTabUtil::ResolvePossiblyRelativeURL("path", extension.get()), |
| 131 | GURL("chrome-extension://jpignaibiiemhngfjkcpokkamffknabf/path")); |
| 132 | EXPECT_EQ(ExtensionTabUtil::ResolvePossiblyRelativeURL("path", nullptr), |
| 133 | GURL("path")); |
| 134 | } |
| 135 | |
Tim Judkins | 495a667 | 2020-05-11 23:08:28 | [diff] [blame] | 136 | TEST(ExtensionTabUtilTest, PrepareURLForNavigation) { |
| 137 | auto extension = ExtensionBuilder("test").Build(); |
| 138 | // A fully qualified URL should return the same URL. |
| 139 | { |
| 140 | const std::string kTestUrl("http://google.com"); |
| 141 | std::string error; |
| 142 | GURL url; |
| 143 | EXPECT_TRUE(ExtensionTabUtil::PrepareURLForNavigation( |
| 144 | kTestUrl, extension.get(), &url, &error)); |
| 145 | EXPECT_EQ(GURL(kTestUrl), url); |
| 146 | EXPECT_EQ("", error); |
| 147 | } |
| 148 | // A relative path should return a URL relative to the extension's base URL. |
| 149 | { |
| 150 | const std::string kTestPath("foo"); |
| 151 | std::string error; |
| 152 | GURL url; |
| 153 | EXPECT_TRUE(ExtensionTabUtil::PrepareURLForNavigation( |
| 154 | kTestPath, extension.get(), &url, &error)); |
| 155 | EXPECT_EQ(extension->GetResourceURL(kTestPath), url); |
| 156 | EXPECT_EQ("", error); |
| 157 | } |
| 158 | // A kill URL should return false and set the error. There are several |
| 159 | // different potential kill URLs and this just checks one of them. |
| 160 | { |
| 161 | const std::string kKillURL("chrome://crash"); |
| 162 | std::string error; |
| 163 | GURL url; |
| 164 | EXPECT_FALSE(ExtensionTabUtil::PrepareURLForNavigation( |
| 165 | kKillURL, extension.get(), &url, &error)); |
| 166 | EXPECT_EQ(tabs_constants::kNoCrashBrowserError, error); |
| 167 | } |
| 168 | } |
| 169 | |
Tim Judkins | 5edf2d6 | 2020-11-26 00:41:01 | [diff] [blame] | 170 | TEST(ExtensionTabUtilTest, PrepareURLForNavigationOnDevtools) { |
| 171 | const std::string kDevtoolsURL( |
| 172 | "devtools://devtools/bundled/devtools_app.html"); |
| 173 | // A devtools url should return false and set the error. |
| 174 | { |
| 175 | auto no_permission_extension = ExtensionBuilder("none").Build(); |
| 176 | std::string error; |
| 177 | GURL url; |
| 178 | EXPECT_FALSE(ExtensionTabUtil::PrepareURLForNavigation( |
| 179 | kDevtoolsURL, no_permission_extension.get(), &url, &error)); |
| 180 | EXPECT_EQ(tabs_constants::kCannotNavigateToDevtools, error); |
| 181 | } |
| 182 | // Having the devtools permissions should allow access. |
| 183 | { |
| 184 | auto devtools_extension = ExtensionBuilder("devtools") |
| 185 | .SetManifestKey("devtools_page", "foo.html") |
| 186 | .Build(); |
| 187 | std::string error; |
| 188 | GURL url; |
| 189 | EXPECT_TRUE(ExtensionTabUtil::PrepareURLForNavigation( |
| 190 | kDevtoolsURL, devtools_extension.get(), &url, &error)); |
| 191 | EXPECT_EQ(kDevtoolsURL, url); |
| 192 | EXPECT_TRUE(error.empty()); |
| 193 | } |
| 194 | // Having the debugger permissions should also allow access. |
| 195 | { |
| 196 | auto debugger_extension = |
| 197 | ExtensionBuilder("debugger").AddPermission("debugger").Build(); |
| 198 | std::string error; |
| 199 | GURL url; |
| 200 | EXPECT_TRUE(ExtensionTabUtil::PrepareURLForNavigation( |
| 201 | kDevtoolsURL, debugger_extension.get(), &url, &error)); |
| 202 | EXPECT_EQ(kDevtoolsURL, url); |
| 203 | EXPECT_TRUE(error.empty()); |
| 204 | } |
| 205 | } |
| 206 | |
isandrk | e095113 | 2017-04-24 17:53:31 | [diff] [blame] | 207 | } // namespace extensions |