1 // Copyright (c) 2012 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 "extensions/browser/api/web_request/web_request_permissions.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/message_loop/message_loop.h" 9 #include "chrome/common/extensions/extension_test_util.h" 10 #include "content/public/browser/resource_request_info.h" 11 #include "content/public/test/test_browser_thread_bundle.h" 12 #include "extensions/browser/info_map.h" 13 #include "extensions/common/constants.h" 14 #include "ipc/ipc_message.h" 15 #include "net/base/request_priority.h" 16 #include "net/url_request/url_request.h" 17 #include "net/url_request/url_request_test_util.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 using content::ResourceRequestInfo; 21 using content::ResourceType; 22 using extensions::Extension; 23 using extensions::Manifest; 24 using extension_test_util::LoadManifestUnchecked; 25 26 class ExtensionWebRequestHelpersTestWithThreadsTest : public testing::Test { 27 public: 28 ExtensionWebRequestHelpersTestWithThreadsTest() 29 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} 30 31 protected: 32 virtual void SetUp() OVERRIDE; 33 34 protected: 35 net::TestURLRequestContext context; 36 37 // This extension has Web Request permissions, but no host permission. 38 scoped_refptr<Extension> permissionless_extension_; 39 // This extension has Web Request permissions, and *.com a host permission. 40 scoped_refptr<Extension> com_extension_; 41 scoped_refptr<extensions::InfoMap> extension_info_map_; 42 43 private: 44 content::TestBrowserThreadBundle thread_bundle_; 45 }; 46 47 void ExtensionWebRequestHelpersTestWithThreadsTest::SetUp() { 48 testing::Test::SetUp(); 49 50 std::string error; 51 permissionless_extension_ = LoadManifestUnchecked("permissions", 52 "web_request_no_host.json", 53 Manifest::INVALID_LOCATION, 54 Extension::NO_FLAGS, 55 "ext_id_1", 56 &error); 57 ASSERT_TRUE(permissionless_extension_.get()) << error; 58 com_extension_ = 59 LoadManifestUnchecked("permissions", 60 "web_request_com_host_permissions.json", 61 Manifest::INVALID_LOCATION, 62 Extension::NO_FLAGS, 63 "ext_id_2", 64 &error); 65 ASSERT_TRUE(com_extension_.get()) << error; 66 extension_info_map_ = new extensions::InfoMap; 67 extension_info_map_->AddExtension(permissionless_extension_.get(), 68 base::Time::Now(), 69 false /*incognito_enabled*/, 70 false /*notifications_disabled*/); 71 extension_info_map_->AddExtension( 72 com_extension_.get(), 73 base::Time::Now(), 74 false /*incognito_enabled*/, 75 false /*notifications_disabled*/); 76 } 77 78 TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, TestHideRequestForURL) { 79 net::TestURLRequestContext context; 80 const char* sensitive_urls[] = { 81 "http://clients2.google.com", 82 "http://clients22.google.com", 83 "https://clients2.google.com", 84 "http://clients2.google.com/service/update2/crx", 85 "https://clients.google.com", 86 "https://test.clients.google.com", 87 "https://clients2.google.com/service/update2/crx", 88 "http://www.gstatic.com/chrome/extensions/blacklist", 89 "https://www.gstatic.com/chrome/extensions/blacklist", 90 "notregisteredscheme://www.foobar.com", 91 "https://chrome.google.com/webstore/", 92 "https://chrome.google.com/webstore/" 93 "inlineinstall/detail/kcnhkahnjcbndmmehfkdnkjomaanaooo" 94 }; 95 const char* non_sensitive_urls[] = { 96 "http://www.google.com/" 97 }; 98 const int kSigninProcessId = 99; 99 extension_info_map_->SetSigninProcess(kSigninProcessId); 100 101 // Check that requests are rejected based on the destination 102 for (size_t i = 0; i < arraysize(sensitive_urls); ++i) { 103 GURL sensitive_url(sensitive_urls[i]); 104 scoped_ptr<net::URLRequest> request(context.CreateRequest( 105 sensitive_url, net::DEFAULT_PRIORITY, NULL, NULL)); 106 EXPECT_TRUE(WebRequestPermissions::HideRequest( 107 extension_info_map_.get(), request.get())) << sensitive_urls[i]; 108 } 109 // Check that requests are accepted if they don't touch sensitive urls. 110 for (size_t i = 0; i < arraysize(non_sensitive_urls); ++i) { 111 GURL non_sensitive_url(non_sensitive_urls[i]); 112 scoped_ptr<net::URLRequest> request(context.CreateRequest( 113 non_sensitive_url, net::DEFAULT_PRIORITY, NULL, NULL)); 114 EXPECT_FALSE(WebRequestPermissions::HideRequest( 115 extension_info_map_.get(), request.get())) << non_sensitive_urls[i]; 116 } 117 118 // Check protection of requests originating from the frame showing the Chrome 119 // WebStore. 120 // Normally this request is not protected: 121 GURL non_sensitive_url("http://www.google.com/test.js"); 122 scoped_ptr<net::URLRequest> non_sensitive_request(context.CreateRequest( 123 non_sensitive_url, net::DEFAULT_PRIORITY, NULL, NULL)); 124 EXPECT_FALSE(WebRequestPermissions::HideRequest( 125 extension_info_map_.get(), non_sensitive_request.get())); 126 // If the origin is labeled by the WebStoreAppId, it becomes protected. 127 { 128 int process_id = 42; 129 int site_instance_id = 23; 130 int view_id = 17; 131 scoped_ptr<net::URLRequest> sensitive_request(context.CreateRequest( 132 non_sensitive_url, net::DEFAULT_PRIORITY, NULL, NULL)); 133 ResourceRequestInfo::AllocateForTesting(sensitive_request.get(), 134 content::RESOURCE_TYPE_SCRIPT, 135 NULL, 136 process_id, 137 view_id, 138 MSG_ROUTING_NONE, 139 false); 140 extension_info_map_->RegisterExtensionProcess( 141 extensions::kWebStoreAppId, process_id, site_instance_id); 142 EXPECT_TRUE(WebRequestPermissions::HideRequest( 143 extension_info_map_.get(), sensitive_request.get())); 144 } 145 // If the process is the signin process, it becomes protected. 146 { 147 int process_id = kSigninProcessId; 148 int view_id = 19; 149 scoped_ptr<net::URLRequest> sensitive_request(context.CreateRequest( 150 non_sensitive_url, net::DEFAULT_PRIORITY, NULL, NULL)); 151 ResourceRequestInfo::AllocateForTesting(sensitive_request.get(), 152 content::RESOURCE_TYPE_SCRIPT, 153 NULL, 154 process_id, 155 view_id, 156 MSG_ROUTING_NONE, 157 false); 158 EXPECT_TRUE(WebRequestPermissions::HideRequest( 159 extension_info_map_.get(), sensitive_request.get())); 160 } 161 } 162 163 TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, 164 TestCanExtensionAccessURL_HostPermissions) { 165 scoped_ptr<net::URLRequest> request(context.CreateRequest( 166 GURL("http://example.com"), net::DEFAULT_PRIORITY, NULL, NULL)); 167 168 EXPECT_TRUE(WebRequestPermissions::CanExtensionAccessURL( 169 extension_info_map_.get(), 170 permissionless_extension_->id(), 171 request->url(), 172 false /*crosses_incognito*/, 173 WebRequestPermissions::DO_NOT_CHECK_HOST)); 174 EXPECT_FALSE(WebRequestPermissions::CanExtensionAccessURL( 175 extension_info_map_.get(), 176 permissionless_extension_->id(), 177 request->url(), 178 false /*crosses_incognito*/, 179 WebRequestPermissions::REQUIRE_HOST_PERMISSION)); 180 EXPECT_TRUE(WebRequestPermissions::CanExtensionAccessURL( 181 extension_info_map_.get(), 182 com_extension_->id(), 183 request->url(), 184 false /*crosses_incognito*/, 185 WebRequestPermissions::REQUIRE_HOST_PERMISSION)); 186 EXPECT_FALSE(WebRequestPermissions::CanExtensionAccessURL( 187 extension_info_map_.get(), 188 com_extension_->id(), 189 request->url(), 190 false /*crosses_incognito*/, 191 WebRequestPermissions::REQUIRE_ALL_URLS)); 192 } 193