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
20using content::ResourceRequestInfo;
21using content::ResourceType;
22using extensions::Extension;
23using extensions::Manifest;
24using extension_test_util::LoadManifestUnchecked;
25
26class 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
47void 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
78TEST_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
163TEST_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