summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaren@chromium.org <karen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-15 22:14:58 +0000
committerkaren@chromium.org <karen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-15 22:14:58 +0000
commitb00aa0204f72bd60e7808a9daf3cd1fcb0df81bb (patch)
tree8051f3fa477bf278c8da014d158bf19dfb47190e
parentb38236af7251c13b6d0f58a6ee002c3fe1bd3d04 (diff)
downloadchromium_src-b00aa0204f72bd60e7808a9daf3cd1fcb0df81bb.zip
chromium_src-b00aa0204f72bd60e7808a9daf3cd1fcb0df81bb.tar.gz
chromium_src-b00aa0204f72bd60e7808a9daf3cd1fcb0df81bb.tar.bz2
Merge 121111 - Add a centralized mechanism for whitelisting access to extension permissions.
This also updates the following permissions to use the whitelist: - terminalPrivate - webSocketProxyPrivate - chromePrivate - inputMethodPrivate - chromeAuthPrivate - webstorePrivate Includes more tests to verify that Extension loading fails for different permission parameters: - by extension type - component only flag - whitelists BUG=84211, 111314 TEST=extension unit and browser tests Review URL: http://codereview.chromium.org/9317013 TBR=jstritar@chromium.org Review URL: https://chromiumcodereview.appspot.com/9703090 git-svn-id: svn://svn.chromium.org/chrome/branches/1025/src@127007 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chrome_content_browser_client.cc12
-rw-r--r--chrome/browser/chromeos/extensions/input_method_event_router.cc46
-rw-r--r--chrome/browser/chromeos/extensions/input_method_event_router.h5
-rw-r--r--chrome/browser/chromeos/web_socket_proxy.cc23
-rw-r--r--chrome/browser/chromeos/web_socket_proxy.h5
-rw-r--r--chrome/browser/chromeos/web_socket_proxy_controller.cc85
-rw-r--r--chrome/browser/chromeos/web_socket_proxy_controller.h12
-rw-r--r--chrome/browser/extensions/api/terminal/terminal_private_api.cc33
-rw-r--r--chrome/browser/extensions/extension_chrome_auth_private_api.cc24
-rw-r--r--chrome/browser/extensions/extension_chrome_auth_private_apitest.cc10
-rw-r--r--chrome/browser/extensions/extension_chrome_private_apitest.cc19
-rw-r--r--chrome/browser/extensions/extension_decode_jpeg_apitest.cc9
-rw-r--r--chrome/browser/extensions/extension_input_method_api.cc15
-rw-r--r--chrome/browser/extensions/extension_input_method_apitest.cc14
-rw-r--r--chrome/browser/extensions/extension_web_socket_proxy_private_api.cc33
-rw-r--r--chrome/browser/extensions/extension_web_socket_proxy_private_apitest.cc5
-rw-r--r--chrome/browser/extensions/extension_webstore_private_api.cc32
-rw-r--r--chrome/chrome_tests.gypi2
-rw-r--r--chrome/common/chrome_switches.cc6
-rw-r--r--chrome/common/chrome_switches.h2
-rw-r--r--chrome/common/extensions/extension.cc33
-rw-r--r--chrome/common/extensions/extension.h1
-rw-r--r--chrome/common/extensions/extension_constants.cc6
-rw-r--r--chrome/common/extensions/extension_constants.h18
-rw-r--r--chrome/common/extensions/extension_manifests_unittest.cc100
-rw-r--r--chrome/common/extensions/extension_permission_set.cc104
-rw-r--r--chrome/common/extensions/extension_permission_set.h26
-rw-r--r--chrome/common/extensions/extension_permission_set_unittest.cc216
-rw-r--r--chrome/renderer/extensions/chrome_private_custom_bindings.cc13
-rw-r--r--chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/background.html6
-rw-r--r--chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/cloud_print_exception.js28
-rw-r--r--chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/manifest.json12
-rw-r--r--chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/background.html6
-rw-r--r--chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/cloud_print_fail.js19
-rw-r--r--chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/manifest.json13
-rw-r--r--chrome/test/data/extensions/api_test/terminal/component_extension/background.html5
-rw-r--r--chrome/test/data/extensions/api_test/terminal/component_extension/manifest.json3
-rw-r--r--chrome/test/data/extensions/api_test/terminal/no_permission/manifest.json9
-rw-r--r--chrome/test/data/extensions/api_test/terminal/no_permission/test.js20
39 files changed, 383 insertions, 647 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index aa330cd..1632936 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -684,15 +684,19 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
switches::kProfilingFile,
switches::kProfilingFlush,
switches::kSilentDumpOnDCHECK,
+ switches::kWhitelistedExtensionID,
};
command_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
arraysize(kSwitchNames));
} else if (process_type == switches::kUtilityProcess) {
- if (browser_command_line.HasSwitch(
- switches::kEnableExperimentalExtensionApis)) {
- command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis);
- }
+ static const char* const kSwitchNames[] = {
+ switches::kEnableExperimentalExtensionApis,
+ switches::kWhitelistedExtensionID,
+ };
+
+ command_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
+ arraysize(kSwitchNames));
} else if (process_type == switches::kPluginProcess) {
static const char* const kSwitchNames[] = {
#if defined(OS_CHROMEOS)
diff --git a/chrome/browser/chromeos/extensions/input_method_event_router.cc b/chrome/browser/chromeos/extensions/input_method_event_router.cc
index 18a06f6..975c157 100644
--- a/chrome/browser/chromeos/extensions/input_method_event_router.cc
+++ b/chrome/browser/chromeos/extensions/input_method_event_router.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -7,7 +7,6 @@
#include <algorithm>
#include "base/json/json_writer.h"
-#include "base/lazy_instance.h"
#include "base/values.h"
#include "chrome/browser/chromeos/web_socket_proxy_controller.h"
#include "chrome/browser/extensions/extension_event_names.h"
@@ -20,30 +19,6 @@ namespace {
// Prefix, which is used by XKB.
const char kXkbPrefix[] = "xkb:";
-// Extension ID which is used in browser_tests.
-const char kInputMethodTestExtensionID[] = "ilanclmaeigfpnmdlgelmhkpkegdioip";
-
-class InputMethodPrivateExtensionsWhitelist {
- public:
- InputMethodPrivateExtensionsWhitelist() {
- chromeos::FillWithExtensionsIdsWithPrivateAccess(&ids_);
- ids_.push_back(kInputMethodTestExtensionID);
- std::sort(ids_.begin(), ids_.end());
- }
-
- bool HasId(const std::string& id) {
- return std::binary_search(ids_.begin(), ids_.end(), id);
- }
-
- const std::vector<std::string>& ids() { return ids_; }
-
- private:
- std::vector<std::string> ids_;
-};
-
-base::LazyInstance<InputMethodPrivateExtensionsWhitelist>
- g_input_method_private_extensions_whitelist = LAZY_INSTANCE_INITIALIZER;
-
} // namespace
namespace chromeos {
@@ -73,16 +48,10 @@ void ExtensionInputMethodEventRouter::InputMethodChanged(
std::string args_json;
base::JSONWriter::Write(&args, false, &args_json);
- const std::vector<std::string>& ids =
- g_input_method_private_extensions_whitelist.Get().ids();
-
- for (size_t i = 0; i < ids.size(); ++i) {
- // ExtensionEventRoutner will check that the extension is listening for the
- // event.
- router->DispatchEventToExtension(
- ids[i], extension_event_names::kOnInputMethodChanged,
- args_json, profile, GURL());
- }
+ // The router will only send the event to extensions that are listening.
+ router->DispatchEventToRenderers(
+ extension_event_names::kOnInputMethodChanged,
+ args_json, profile, GURL());
}
void ExtensionInputMethodEventRouter::ActiveInputMethodsChanged(
@@ -103,9 +72,4 @@ std::string ExtensionInputMethodEventRouter::GetInputMethodForXkb(
return xkb_id.substr(prefix_length);
}
-bool ExtensionInputMethodEventRouter::IsExtensionWhitelisted(
- const std::string& extension_id) {
- return g_input_method_private_extensions_whitelist.Get().HasId(extension_id);
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/input_method_event_router.h b/chrome/browser/chromeos/extensions/input_method_event_router.h
index 1dc7412..f9ba5d7 100644
--- a/chrome/browser/chromeos/extensions/input_method_event_router.h
+++ b/chrome/browser/chromeos/extensions/input_method_event_router.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -34,9 +34,6 @@ class ExtensionInputMethodEventRouter
// Window System) id.
std::string GetInputMethodForXkb(const std::string& xkb_id);
- // Returns whether the extension is allowed to use input method API.
- bool IsExtensionWhitelisted(const std::string& extension_id);
-
private:
DISALLOW_COPY_AND_ASSIGN(ExtensionInputMethodEventRouter);
};
diff --git a/chrome/browser/chromeos/web_socket_proxy.cc b/chrome/browser/chromeos/web_socket_proxy.cc
index 53ce784..66a3e1a 100644
--- a/chrome/browser/chromeos/web_socket_proxy.cc
+++ b/chrome/browser/chromeos/web_socket_proxy.cc
@@ -177,7 +177,7 @@ class Conn;
// Websocket to TCP proxy server.
class Serv {
public:
- explicit Serv(const std::vector<std::string>& allowed_origins);
+ Serv();
~Serv();
// Do not call it twice.
@@ -192,7 +192,6 @@ class Serv {
void MarkConnImportance(Conn*, bool important);
Conn* GetFreshConn();
bool IsConnSane(Conn*);
- bool IsOriginAllowed(const std::string& origin);
void CloseAll();
static void OnConnect(int listening_sock, short event, void*);
@@ -200,10 +199,6 @@ class Serv {
struct event_base* evbase() { return evbase_; }
- // Checked against value of Origin field specified
- // in a client websocket handshake.
- std::vector<std::string> allowed_origins_;
-
// Libevent base.
struct event_base* evbase_;
@@ -803,13 +798,11 @@ class SSLChan : public MessageLoopForIO::Watcher {
DISALLOW_COPY_AND_ASSIGN(SSLChan);
};
-Serv::Serv(const std::vector<std::string>& allowed_origins)
- : allowed_origins_(allowed_origins),
- evbase_(NULL),
+Serv::Serv()
+ : evbase_(NULL),
listening_sock_(-1),
extra_listening_sock_(-1),
shutdown_requested_(false) {
- std::sort(allowed_origins_.begin(), allowed_origins_.end());
control_descriptor_[0] = -1;
control_descriptor_[1] = -1;
}
@@ -1052,11 +1045,6 @@ bool Serv::IsConnSane(Conn* cs) {
return rev_map_.find(cs) != rev_map_.end();
}
-bool Serv::IsOriginAllowed(const std::string& origin) {
- return allowed_origins_.empty() || std::binary_search(
- allowed_origins_.begin(), allowed_origins_.end(), origin);
-}
-
// static
void Serv::OnConnect(int listening_sock, short event, void* ctx) {
Serv* self = static_cast<Serv*>(ctx);
@@ -1265,8 +1253,6 @@ Conn::Status Conn::ConsumeHeader(struct evbuffer* evb) {
GURL origin = GURL(GetOrigin()).GetOrigin();
if (!origin.is_valid())
return STATUS_ABORT;
- if (!master_->IsOriginAllowed(origin.spec()))
- return STATUS_ABORT;
if (!requested_parameters_.empty()) {
destname_ = requested_parameters_["hostname"];
@@ -1898,8 +1884,7 @@ base::LazyInstance<Conn::EventKeyMap>::Leaky
} // namespace
-WebSocketProxy::WebSocketProxy(const std::vector<std::string>& allowed_origins)
- : impl_(new Serv(allowed_origins)) {
+WebSocketProxy::WebSocketProxy() : impl_(new Serv()) {
}
WebSocketProxy::~WebSocketProxy() {
diff --git a/chrome/browser/chromeos/web_socket_proxy.h b/chrome/browser/chromeos/web_socket_proxy.h
index 5e2fb3b..08436f5 100644
--- a/chrome/browser/chromeos/web_socket_proxy.h
+++ b/chrome/browser/chromeos/web_socket_proxy.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -22,8 +22,7 @@ class WebSocketProxy {
// Limits number of simultaneously open connections.
static const size_t kConnPoolLimit = 40;
- // Empty |allowed_origins| vector disables check for origin.
- explicit WebSocketProxy(const std::vector<std::string>& allowed_origins);
+ WebSocketProxy();
~WebSocketProxy();
// Do not call it twice.
diff --git a/chrome/browser/chromeos/web_socket_proxy_controller.cc b/chrome/browser/chromeos/web_socket_proxy_controller.cc
index 478e3c2..50d286c 100644
--- a/chrome/browser/chromeos/web_socket_proxy_controller.cc
+++ b/chrome/browser/chromeos/web_socket_proxy_controller.cc
@@ -32,72 +32,6 @@
namespace {
-const char* kAllowedIds[] = {
- "haiffjcadagjlijoggckpgfnoeiflnem",
- "gnedhmakppccajfpfiihfcdlnpgomkcf",
- "fjcibdnjlbfnbfdjneajpipnlcppleek",
- "okddffdblfhhnmhodogpojmfkjmhinfp",
- "pnhechapfaindjhompbnflcldabbghjo" // HTerm App (SSH Client)
-};
-
-class OriginValidator {
- public:
- OriginValidator() {
- chromeos::FillWithExtensionsIdsWithPrivateAccess(&allowed_ids_);
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- DCHECK(command_line);
- std::string allowed_list =
- command_line->GetSwitchValueASCII(switches::kAllowWebSocketProxy);
- if (!allowed_list.empty()) {
- StringTokenizer t(allowed_list, ",");
- while (t.GetNext()) {
- // It must be either extension id or origin.
- if (Extension::IdIsValid(t.token())) {
- allowed_ids_.push_back(t.token());
- } else {
- // It is not extension id, check if it is an origin.
- GURL origin = GURL(t.token()).GetOrigin();
- if (!origin.is_valid()) {
- LOG(ERROR) << "Invalid extension id or origin specified via "
- << switches::kAllowWebSocketProxy << " switch";
- break;
- }
- allowed_origins_.push_back(origin.spec());
- if (origin.SchemeIs(chrome::kExtensionScheme))
- allowed_ids_.push_back(origin.host());
- }
- }
- }
- for (size_t i = 0; i < allowed_ids_.size(); ++i) {
- allowed_origins_.push_back(Extension::GetBaseURLFromExtensionId(
- allowed_ids_[i]).GetOrigin().spec());
- }
- std::sort(allowed_ids_.begin(), allowed_ids_.end());
- allowed_ids_.resize(std::unique(
- allowed_ids_.begin(), allowed_ids_.end()) - allowed_ids_.begin());
- std::sort(allowed_origins_.begin(), allowed_origins_.end());
- allowed_origins_.resize(std::unique(allowed_origins_.begin(),
- allowed_origins_.end()) - allowed_origins_.begin());
- }
-
- bool CheckCredentials(
- const std::string& extension_id,
- const std::string& hostname,
- unsigned short port,
- chromeos::WebSocketProxyController::ConnectionFlags flags) {
- return std::binary_search(
- allowed_ids_.begin(), allowed_ids_.end(), extension_id);
- }
-
- const std::vector<std::string>& allowed_origins() { return allowed_origins_; }
-
- private:
- std::vector<std::string> allowed_ids_;
- std::vector<std::string> allowed_origins_;
-};
-
-base::LazyInstance<OriginValidator> g_validator = LAZY_INSTANCE_INITIALIZER;
-
class ProxyLifetime
: public net::NetworkChangeNotifier::OnlineStateObserver,
public content::NotificationObserver {
@@ -145,8 +79,7 @@ class ProxyLifetime
void ProxyCallback() {
LOG(INFO) << "Attempt to run web socket proxy task";
- chromeos::WebSocketProxy* server = new chromeos::WebSocketProxy(
- g_validator.Get().allowed_origins());
+ chromeos::WebSocketProxy* server = new chromeos::WebSocketProxy();
{
base::AutoLock alk(lock_);
if (shutdown_requested_)
@@ -193,12 +126,6 @@ base::LazyInstance<ProxyLifetime> g_proxy_lifetime = LAZY_INSTANCE_INITIALIZER;
namespace chromeos {
-void FillWithExtensionsIdsWithPrivateAccess(std::vector<std::string>* ids) {
- ids->clear();
- for (size_t i = 0; i < arraysize(kAllowedIds); ++i)
- ids->push_back(kAllowedIds[i]);
-}
-
// static
void WebSocketProxyController::Initiate() {
g_proxy_lifetime.Get();
@@ -231,14 +158,4 @@ void WebSocketProxyController::Shutdown() {
g_proxy_lifetime.Get().web_socket_proxy_thread_.Stop();
}
-// static
-bool WebSocketProxyController::CheckCredentials(
- const std::string& extension_id,
- const std::string& hostname,
- unsigned short port,
- ConnectionFlags flags) {
- return g_validator.Get().CheckCredentials(
- extension_id, hostname, port, flags);
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/web_socket_proxy_controller.h b/chrome/browser/chromeos/web_socket_proxy_controller.h
index 4e8ad0d..bfde94e 100644
--- a/chrome/browser/chromeos/web_socket_proxy_controller.h
+++ b/chrome/browser/chromeos/web_socket_proxy_controller.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -11,10 +11,6 @@
namespace chromeos {
-// Fills vector with extensions IDs which are allowed to use private
-// extension API (WebSocketProxyPrivate, InputMethodPrivate, etc.)
-void FillWithExtensionsIdsWithPrivateAccess(std::vector<std::string>* ids);
-
// Controls webproxy to TCP service.
class WebSocketProxyController {
public:
@@ -30,12 +26,6 @@ class WebSocketProxyController {
static void Shutdown();
static bool IsInitiated();
static int GetPort(); // Returns port listening websocket connections.
-
- static bool CheckCredentials(
- const std::string& extension_id,
- const std::string& hostname,
- unsigned short port,
- ConnectionFlags);
};
} // namespace chromeos
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index be76747..bf9140a 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -22,32 +22,6 @@ const char kCroshCommand[] = "/usr/bin/crosh";
// We make stubbed crosh just echo back input.
const char kStubbedCroshCommand[] = "cat";
-const char kPermissionError[] =
- "Extension does not have the permission to use this API";
-
-const char* kAllowedExtensionIds[] ={
- "okddffdblfhhnmhodogpojmfkjmhinfp", // test SSH/Crosh Client
- "pnhechapfaindjhompbnflcldabbghjo" // HTerm App
-};
-
-// Allow component and whitelisted extensions.
-bool AllowAccessToExtension(Profile* profile, const std::string& extension_id) {
- ExtensionService* service = profile->GetExtensionService();
- const Extension* extension = service->GetExtensionById(extension_id, false);
-
- if (!extension)
- return false;
-
- if (extension->location() == Extension::COMPONENT)
- return true;
-
- for (size_t i = 0; i < arraysize(kAllowedExtensionIds); i++) {
- if (extension->id() == kAllowedExtensionIds[i])
- return true;
- }
- return false;
-}
-
const char* GetCroshPath() {
if (chromeos::system::runtime_environment::IsRunningOnChromeOS())
return kCroshCommand;
@@ -75,8 +49,6 @@ void NotifyProcessOutput(Profile* profile,
return;
}
- CHECK(AllowAccessToExtension(profile, extension_id));
-
base::ListValue args;
args.Append(new base::FundamentalValue(pid));
args.Append(new base::StringValue(output_type));
@@ -101,11 +73,6 @@ TerminalPrivateFunction::~TerminalPrivateFunction() {
}
bool TerminalPrivateFunction::RunImpl() {
- if (!AllowAccessToExtension(profile_, extension_id())) {
- error_ = kPermissionError;
- return false;
- }
-
return RunTerminalFunction();
}
diff --git a/chrome/browser/extensions/extension_chrome_auth_private_api.cc b/chrome/browser/extensions/extension_chrome_auth_private_api.cc
index 1f4e6db..fcc4e2b 100644
--- a/chrome/browser/extensions/extension_chrome_auth_private_api.cc
+++ b/chrome/browser/extensions/extension_chrome_auth_private_api.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -13,24 +13,8 @@
namespace {
-bool IsCloudPrintEnableURL(Profile* profile, const GURL& url) {
- ExtensionService* service = profile->GetExtensionService();
- const Extension* cloud_print_app = service->GetExtensionById(
- extension_misc::kCloudPrintAppId, false);
- if (!cloud_print_app) {
-#if !defined(OS_CHROMEOS)
- NOTREACHED();
-#endif // !defined(OS_CHROMEOS)
- return false;
- }
- return (service->extensions()->GetHostedAppByURL(ExtensionURLInfo(url)) ==
- cloud_print_app);
-}
-
bool test_mode = false;
-const char kAccessDeniedError[] =
- "Cannot call this API from a non-cloudprint URL.";
} // namespace
SetCloudPrintCredentialsFunction::SetCloudPrintCredentialsFunction() {
@@ -40,12 +24,6 @@ SetCloudPrintCredentialsFunction::~SetCloudPrintCredentialsFunction() {
}
bool SetCloudPrintCredentialsFunction::RunImpl() {
- // This has to be called from the specific cloud print app.
- if (!IsCloudPrintEnableURL(profile_, source_url())) {
- error_ = kAccessDeniedError;
- return false;
- }
-
std::string user_email;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &user_email));
std::string robot_email;
diff --git a/chrome/browser/extensions/extension_chrome_auth_private_apitest.cc b/chrome/browser/extensions/extension_chrome_auth_private_apitest.cc
index b35ef72a..a7a2c57 100644
--- a/chrome/browser/extensions/extension_chrome_auth_private_apitest.cc
+++ b/chrome/browser/extensions/extension_chrome_auth_private_apitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -58,11 +58,3 @@ IN_PROC_BROWSER_TEST_F(ExtensionChromeAuthPrivateApiTest,
SetCloudPrintCredentialsFunction::SetTestMode(false);
}
#endif // !defined(OS_CHROMEOS)
-
-IN_PROC_BROWSER_TEST_F(ExtensionChromeAuthPrivateApiTest,
- SetCloudPrintCredentialsFailureInstalledComponent) {
- // Run this as an installed component app. This should also fail because of
- // the explicit URL check in the API.
- ASSERT_TRUE(RunComponentExtensionTest(
- "chrome_auth_private/installed_component_app"));
-}
diff --git a/chrome/browser/extensions/extension_chrome_private_apitest.cc b/chrome/browser/extensions/extension_chrome_private_apitest.cc
new file mode 100644
index 0000000..37203b7
--- /dev/null
+++ b/chrome/browser/extensions/extension_chrome_private_apitest.cc
@@ -0,0 +1,19 @@
+// Copyright (c) 2012 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 "base/command_line.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/common/chrome_switches.h"
+
+class ExtensionChromePrivateApiTest : public ExtensionApiTest {
+ virtual void SetUpCommandLine(CommandLine* command_line) {
+ ExtensionApiTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(
+ switches::kWhitelistedExtensionID, "oflbaaikkabfdfkimeclgkackhdkpnip");
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(ExtensionChromePrivateApiTest, DecodeJPEG) {
+ ASSERT_TRUE(RunExtensionTest("decode_jpeg")) << message_;
+}
diff --git a/chrome/browser/extensions/extension_decode_jpeg_apitest.cc b/chrome/browser/extensions/extension_decode_jpeg_apitest.cc
deleted file mode 100644
index bd917f8..0000000
--- a/chrome/browser/extensions/extension_decode_jpeg_apitest.cc
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2011 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 "chrome/browser/extensions/extension_apitest.h"
-
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DecodeJPEG) {
- ASSERT_TRUE(RunExtensionTest("decode_jpeg")) << message_;
-}
diff --git a/chrome/browser/extensions/extension_input_method_api.cc b/chrome/browser/extensions/extension_input_method_api.cc
index cf2bbd2..040bbbb 100644
--- a/chrome/browser/extensions/extension_input_method_api.cc
+++ b/chrome/browser/extensions/extension_input_method_api.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -10,12 +10,6 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
-namespace {
-
-const char kErrorInputMethodPrivateApi[] = "Input method API is private";
-
-} // namespace
-
GetInputMethodFunction::GetInputMethodFunction() {
}
@@ -24,15 +18,10 @@ GetInputMethodFunction::~GetInputMethodFunction() {
bool GetInputMethodFunction::RunImpl() {
#if !defined(OS_CHROMEOS)
- error_ = kErrorInputMethodPrivateApi;
- return false;
+ NOTREACHED();
#else
chromeos::ExtensionInputMethodEventRouter* router =
profile_->GetExtensionService()->input_method_event_router();
- if (!router->IsExtensionWhitelisted(extension_id())) {
- error_ = kErrorInputMethodPrivateApi;
- return false;
- }
chromeos::input_method::InputMethodManager* manager =
chromeos::input_method::InputMethodManager::GetInstance();
const std::string input_method =
diff --git a/chrome/browser/extensions/extension_input_method_apitest.cc b/chrome/browser/extensions/extension_input_method_apitest.cc
index a019386..6223e05 100644
--- a/chrome/browser/extensions/extension_input_method_apitest.cc
+++ b/chrome/browser/extensions/extension_input_method_apitest.cc
@@ -1,14 +1,16 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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 "chrome/browser/extensions/extension_apitest.h"
+#include "base/command_line.h"
#include "base/stringprintf.h"
#include "chrome/browser/chromeos/extensions/input_method_event_router.h"
#include "chrome/browser/chromeos/input_method/input_method_manager.h"
#include "chrome/browser/extensions/extension_test_api.h"
#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_switches.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
@@ -59,9 +61,17 @@ class SetInputMethodListener : public content::NotificationObserver {
int count_;
};
+class ExtensionInputMethodApiTest : public ExtensionApiTest {
+ virtual void SetUpCommandLine(CommandLine* command_line) {
+ ExtensionApiTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitchASCII(
+ switches::kWhitelistedExtensionID, "ilanclmaeigfpnmdlgelmhkpkegdioip");
+ }
+};
+
} // namespace
-IN_PROC_BROWSER_TEST_F(ExtensionApiTest, InputMethodApiBasic) {
+IN_PROC_BROWSER_TEST_F(ExtensionInputMethodApiTest, Basic) {
// Two test, two calls. See JS code for more info.
SetInputMethodListener listener(2);
diff --git a/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc b/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc
index 367bdfb..be377c2 100644
--- a/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc
+++ b/chrome/browser/extensions/extension_web_socket_proxy_private_api.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -26,11 +26,6 @@
#include "chrome/browser/chromeos/web_socket_proxy_controller.h"
#endif
-namespace {
-const char kPermissionDeniedError[] =
- "Extension does not have permission to use this method.";
-}
-
WebSocketProxyPrivate::WebSocketProxyPrivate()
: port_(-1),
listening_port_(-1),
@@ -106,24 +101,16 @@ bool WebSocketProxyPrivate::RunImpl() {
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &hostname_));
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(1, &port_));
- if (chromeos::WebSocketProxyController::CheckCredentials(
- extension_id(), hostname_, port_,
- do_tls_ ? chromeos::WebSocketProxyController::TLS_OVER_TCP :
- chromeos::WebSocketProxyController::PLAIN_TCP)) {
- listening_port_ = chromeos::WebSocketProxyController::GetPort();
- if (listening_port_ < 1) {
- delay_response = true;
- registrar_.Add(
- this, chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED,
- content::NotificationService::AllSources());
- }
- map_["hostname"] = hostname_;
- map_["port"] = base::IntToString(port_);
- map_["extension_id"] = extension_id();
- } else {
- error_ = kPermissionDeniedError;
- return false;
+ listening_port_ = chromeos::WebSocketProxyController::GetPort();
+ if (listening_port_ < 1) {
+ delay_response = true;
+ registrar_.Add(
+ this, chrome::NOTIFICATION_WEB_SOCKET_PROXY_STARTED,
+ content::NotificationService::AllSources());
}
+ map_["hostname"] = hostname_;
+ map_["port"] = base::IntToString(port_);
+ map_["extension_id"] = extension_id();
if (delay_response) {
const int kTimeout = 12;
diff --git a/chrome/browser/extensions/extension_web_socket_proxy_private_apitest.cc b/chrome/browser/extensions/extension_web_socket_proxy_private_apitest.cc
index 060583e..2a6c4ab 100644
--- a/chrome/browser/extensions/extension_web_socket_proxy_private_apitest.cc
+++ b/chrome/browser/extensions/extension_web_socket_proxy_private_apitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -9,7 +9,7 @@ class ExtensionWebSocketProxyPrivateApiTest : public ExtensionApiTest {
void SetUpCommandLine(CommandLine* command_line) {
ExtensionApiTest::SetUpCommandLine(command_line);
command_line->AppendSwitchASCII(
- switches::kAllowWebSocketProxy, "mknjjldhaihcdajjbihghhiehamnpcak");
+ switches::kWhitelistedExtensionID, "mknjjldhaihcdajjbihghhiehamnpcak");
}
};
@@ -22,4 +22,3 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebSocketProxyPrivateApiTest, Pass) {
ASSERT_TRUE(RunExtensionTest("web_socket_proxy_private")) << message_;
#endif
}
-
diff --git a/chrome/browser/extensions/extension_webstore_private_api.cc b/chrome/browser/extensions/extension_webstore_private_api.cc
index 27ae847..8d18ff6 100644
--- a/chrome/browser/extensions/extension_webstore_private_api.cc
+++ b/chrome/browser/extensions/extension_webstore_private_api.cc
@@ -53,8 +53,6 @@ const char kInvalidManifestError[] = "Invalid manifest";
const char kNoPreviousBeginInstallWithManifestError[] =
"* does not match a previous call to beginInstallWithManifest3";
const char kUserCancelledError[] = "User cancelled install";
-const char kPermissionDeniedError[] =
- "You do not have permission to use this method.";
ProfileSyncService* test_sync_service = NULL;
@@ -68,17 +66,6 @@ ProfileSyncService* GetSyncService(Profile* profile) {
return ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
}
-bool IsWebStoreURL(Profile* profile, const GURL& url) {
- ExtensionService* service = profile->GetExtensionService();
- const Extension* store = service->GetWebStoreApp();
- if (!store) {
- NOTREACHED();
- return false;
- }
- return (service->extensions()->GetHostedAppByURL(ExtensionURLInfo(url)) ==
- store);
-}
-
// Whitelists extension IDs for use by webstorePrivate.silentlyInstall.
bool trust_test_ids = false;
@@ -153,11 +140,6 @@ BeginInstallWithManifestFunction::BeginInstallWithManifestFunction()
BeginInstallWithManifestFunction::~BeginInstallWithManifestFunction() {}
bool BeginInstallWithManifestFunction::RunImpl() {
- if (!IsWebStoreURL(profile_, source_url())) {
- SetResult(PERMISSION_DENIED);
- return false;
- }
-
DictionaryValue* details = NULL;
EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
CHECK(details);
@@ -354,9 +336,6 @@ void BeginInstallWithManifestFunction::InstallUIAbort(bool user_initiated) {
}
bool CompleteInstallFunction::RunImpl() {
- if (!IsWebStoreURL(profile_, source_url()))
- return false;
-
std::string id;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &id));
if (!Extension::IdIsValid(id)) {
@@ -387,11 +366,6 @@ SilentlyInstallFunction::SilentlyInstallFunction() {}
SilentlyInstallFunction::~SilentlyInstallFunction() {}
bool SilentlyInstallFunction::RunImpl() {
- if (!IsWebStoreURL(profile_, source_url())) {
- error_ = kPermissionDeniedError;
- return false;
- }
-
DictionaryValue* details = NULL;
EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details));
CHECK(details);
@@ -467,15 +441,11 @@ void SilentlyInstallFunction::OnExtensionInstallFailure(
}
bool GetBrowserLoginFunction::RunImpl() {
- if (!IsWebStoreURL(profile_, source_url()))
- return false;
result_.reset(CreateLoginResult(profile_->GetOriginalProfile()));
return true;
}
bool GetStoreLoginFunction::RunImpl() {
- if (!IsWebStoreURL(profile_, source_url()))
- return false;
ExtensionService* service = profile_->GetExtensionService();
ExtensionPrefs* prefs = service->extension_prefs();
std::string login;
@@ -488,8 +458,6 @@ bool GetStoreLoginFunction::RunImpl() {
}
bool SetStoreLoginFunction::RunImpl() {
- if (!IsWebStoreURL(profile_, source_url()))
- return false;
std::string login;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &login));
ExtensionService* service = profile_->GetExtensionService();
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 1705c6b..d5964bb 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -2580,6 +2580,7 @@
'browser/extensions/extension_browsertest.h',
'browser/extensions/extension_browsertests_misc.cc',
'browser/extensions/extension_chrome_auth_private_apitest.cc',
+ 'browser/extensions/extension_chrome_private_apitest.cc',
'browser/extensions/extension_clear_test.cc',
'browser/extensions/extension_content_settings_apitest.cc',
'browser/extensions/extension_context_menu_apitest.cc',
@@ -2587,7 +2588,6 @@
'browser/extensions/extension_cookies_apitest.cc',
'browser/extensions/extension_crash_recovery_browsertest.cc',
'browser/extensions/extension_debugger_apitest.cc',
- 'browser/extensions/extension_decode_jpeg_apitest.cc',
'browser/extensions/extension_devtools_browsertest.cc',
'browser/extensions/extension_devtools_browsertest.h',
'browser/extensions/extension_devtools_browsertests.cc',
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 36b10b7..8068ce7 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -50,9 +50,6 @@ const char kAllowRunningInsecureContent[] = "allow-running-insecure-content";
// automation testing of the gallery.
const char kAllowScriptingGallery[] = "allow-scripting-gallery";
-// Specifies comma-separated list of extension ids to grant access to local
-// websocket proxy.
-const char kAllowWebSocketProxy[] = "allow-websocket-proxy";
// Allow compositing on chrome:// pages.
const char kAllowWebUICompositing[] = "allow-webui-compositing";
@@ -1183,6 +1180,9 @@ const char kUserDataDir[] = "user-data-dir";
// Prints version information and quits.
const char kVersion[] = "version";
+// Adds the given extension ID to all the permission whitelists.
+const char kWhitelistedExtensionID[] = "whitelisted-extension-id";
+
// Uses WinHTTP to fetch and evaluate PAC scripts. Otherwise the default is to
// use Chromium's network stack to fetch, and V8 to evaluate.
const char kWinHttpProxyResolver[] = "winhttp-proxy-resolver";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index c9b8e8d..4c285f8 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -31,7 +31,6 @@ extern const char kAllowNaClSocketAPI[];
extern const char kAllowOutdatedPlugins[];
extern const char kAllowRunningInsecureContent[];
extern const char kAllowScriptingGallery[];
-extern const char kAllowWebSocketProxy[];
extern const char kAllowWebUICompositing[];
extern const char kAlwaysAuthorizePlugins[];
extern const char kAppId[];
@@ -322,6 +321,7 @@ extern const char kMaxSpdySessionsPerDomain[];
extern const char kMaxSpdyConcurrentStreams[];
extern const char kUserDataDir[];
extern const char kVersion[];
+extern const char kWhitelistedExtensionID[];
extern const char kWinHttpProxyResolver[];
extern const char kMemoryWidget[];
diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc
index 454230e..9863db4 100644
--- a/chrome/common/extensions/extension.cc
+++ b/chrome/common/extensions/extension.cc
@@ -2853,12 +2853,23 @@ bool Extension::ImplicitlyDelaysNetworkStartup() const {
bool Extension::CanSpecifyAPIPermission(
const ExtensionAPIPermission* permission,
string16* error) const {
- if (permission->is_component_only()) {
- if (!CanSpecifyComponentOnlyPermission()) {
- *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
- errors::kPermissionNotAllowed, permission->name());
- return false;
- }
+ if (location_ == Extension::COMPONENT)
+ return true;
+
+ bool access_denied = false;
+ if (permission->HasWhitelist()) {
+ if (permission->IsWhitelisted(id_))
+ return true;
+ else
+ access_denied = true;
+ } else if (permission->is_component_only()) {
+ access_denied = true;
+ }
+
+ if (access_denied) {
+ *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
+ errors::kPermissionNotAllowed, permission->name());
+ return false;
}
if (permission->id() == ExtensionAPIPermission::kExperimental) {
@@ -2868,9 +2879,6 @@ bool Extension::CanSpecifyAPIPermission(
}
}
- if (location_ == Extension::COMPONENT)
- return true;
-
bool supports_type = false;
switch (GetType()) {
case TYPE_USER_SCRIPT: // Pass through.
@@ -2910,13 +2918,6 @@ bool Extension::CanSpecifyAPIPermission(
return true;
}
-bool Extension::CanSpecifyComponentOnlyPermission() const {
- // Only COMPONENT extensions can use private APIs.
- // TODO(asargent) - We want a more general purpose mechanism for this,
- // and better error messages. (http://crbug.com/54013)
- return location_ == Extension::COMPONENT;
-}
-
bool Extension::CanSpecifyExperimentalPermission() const {
if (location_ == Extension::COMPONENT)
return true;
diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h
index 7bd51eb..f74bae6 100644
--- a/chrome/common/extensions/extension.h
+++ b/chrome/common/extensions/extension.h
@@ -713,7 +713,6 @@ class Extension : public base::RefCountedThreadSafe<Extension> {
// Returns true if this extension can specify |api|.
bool CanSpecifyAPIPermission(const ExtensionAPIPermission* api,
string16* error) const;
- bool CanSpecifyComponentOnlyPermission() const;
bool CanSpecifyExperimentalPermission() const;
// Checks whether the host |pattern| is allowed for this extension, given API
diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc
index 4203070..3ac6212 100644
--- a/chrome/common/extensions/extension_constants.cc
+++ b/chrome/common/extensions/extension_constants.cc
@@ -513,6 +513,12 @@ const char kGeneratedBackgroundPageFilename[] =
namespace extension_misc {
const char kBookmarkManagerId[] = "eemcgdkfndhakfknompkggombfjjjeno";
+const char kCitrixReceiverAppId[] = "haiffjcadagjlijoggckpgfnoeiflnem";
+const char kCitrixReceiverAppBetaId[] = "gnedhmakppccajfpfiihfcdlnpgomkcf";
+const char kCitrixReceiverAppDevId[] = "fjcibdnjlbfnbfdjneajpipnlcppleek";
+const char kEnterpriseWebStoreAppId[] = "afchcafgojfnemjkcbhfekplkmjaldaa";
+const char kHTermAppId[] = "pnhechapfaindjhompbnflcldabbghjo";
+const char kHTermDevAppId[] = "okddffdblfhhnmhodogpojmfkjmhinfp";
const char kWebStoreAppId[] = "ahfgeienlihckogmohjhadlkjgocpleb";
const char kCloudPrintAppId[] = "mfehgcgbbipciphmccgaenjidiccnmng";
const char kAppsPromoHistogram[] = "Extensions.AppsPromo";
diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h
index 2d8baf6..7f68323 100644
--- a/chrome/common/extensions/extension_constants.h
+++ b/chrome/common/extensions/extension_constants.h
@@ -350,6 +350,24 @@ namespace extension_misc {
// The extension id of the bookmark manager.
extern const char kBookmarkManagerId[];
+ // The extension id of the Citrix Receiver application.
+ extern const char kCitrixReceiverAppId[];
+
+ // The extension id of the beta Citrix Receiver application.
+ extern const char kCitrixReceiverAppBetaId[];
+
+ // The extension id of the dev Citrix Receiver application.
+ extern const char kCitrixReceiverAppDevId[];
+
+ // The extension id of the Enterprise Web Store component application.
+ extern const char kEnterpriseWebStoreAppId[];
+
+ // The extension id of the HTerm app for ChromeOS.
+ extern const char kHTermAppId[];
+
+ // The extension id of the HTerm dev app for ChromeOS.
+ extern const char kHTermDevAppId[];
+
// The extension id of the Web Store component application.
extern const char kWebStoreAppId[];
diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc
index 77416e6..4a7dac9 100644
--- a/chrome/common/extensions/extension_manifests_unittest.cc
+++ b/chrome/common/extensions/extension_manifests_unittest.cc
@@ -575,106 +575,6 @@ TEST_F(ExtensionManifestTest, OptionsPageInApps) {
errors::kInvalidOptionsPageExpectUrlInPackage);
}
-TEST_F(ExtensionManifestTest, HostedAppPermissions) {
- std::string error;
- scoped_ptr<DictionaryValue> manifest(
- LoadManifestFile("hosted_app_absolute_options.json", &error));
- ASSERT_TRUE(manifest.get());
- ListValue* permissions = NULL;
- ASSERT_TRUE(manifest->GetList("permissions", &permissions));
-
- int platform_app = ExtensionAPIPermission::kTypePlatformApp;
- ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
- ExtensionAPIPermissionSet api_perms = info->GetAll();
- for (ExtensionAPIPermissionSet::iterator i = api_perms.begin();
- i != api_perms.end(); ++i) {
- if (*i == ExtensionAPIPermission::kExperimental)
- continue;
-
- ExtensionAPIPermission* permission = info->GetByID(*i);
- const char* name = permission->name();
- StringValue* p = new StringValue(name);
- permissions->Clear();
- permissions->Append(p);
-
- // Some permissions are only available to component hosted apps.
- if (permission->is_component_only()) {
- LoadAndExpectError(Manifest(manifest.get(), name),
- errors::kPermissionNotAllowed,
- Extension::INTERNAL);
- scoped_refptr<Extension> extension(
- LoadAndExpectSuccess(Manifest(manifest.get(), name),
- Extension::COMPONENT));
- EXPECT_TRUE(extension->GetActivePermissions()->HasAPIPermission(
- permission->id()));
-
- } else if (permission->type_restrictions() == platform_app) {
- LoadAndExpectError(Manifest(manifest.get(), name),
- errors::kPermissionNotAllowed,
- Extension::INTERNAL,
- Extension::STRICT_ERROR_CHECKS);
- } else if (!permission->supports_hosted_apps()) {
- // Most normal extension permissions also aren't available to hosted apps.
- // For these, the error is only reported in strict mode for legacy
- // reasons: crbug.com/101993.
- LoadAndExpectError(Manifest(manifest.get(), name),
- errors::kPermissionNotAllowed,
- Extension::INTERNAL,
- Extension::STRICT_ERROR_CHECKS);
- scoped_refptr<Extension> extension(
- LoadAndExpectSuccess(Manifest(manifest.get(), name),
- Extension::INTERNAL));
- EXPECT_FALSE(extension->GetActivePermissions()->HasAPIPermission(
- permission->id()));
-
- // These permissions are also allowed for component hosted apps.
- extension = LoadAndExpectSuccess(Manifest(manifest.get(), name),
- Extension::COMPONENT);
- EXPECT_TRUE(extension->GetActivePermissions()->HasAPIPermission(
- permission->id()));
-
- } else {
- scoped_refptr<Extension> extension(
- LoadAndExpectSuccess(Manifest(manifest.get(), name)));
- EXPECT_TRUE(extension->GetActivePermissions()->HasAPIPermission(
- permission->id()));
- }
- }
-}
-
-TEST_F(ExtensionManifestTest, ComponentOnlyPermission) {
- std::string error;
- scoped_ptr<DictionaryValue> manifest(
- LoadManifestFile("init_valid_minimal.json", &error));
- ASSERT_TRUE(manifest.get());
- ListValue* permissions = new ListValue();
- manifest->Set("permissions", permissions);
-
- ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
- ExtensionAPIPermissionSet api_perms = info->GetAll();
- for (ExtensionAPIPermissionSet::iterator i = api_perms.begin();
- i != api_perms.end(); ++i) {
- if (*i == ExtensionAPIPermission::kExperimental)
- continue;
-
- ExtensionAPIPermission* permission = info->GetByID(*i);
- const char* name = permission->name();
- StringValue* p = new StringValue(name);
- permissions->Clear();
- permissions->Append(p);
-
- if (!permission->is_component_only())
- continue;
-
- // Component-only extensions should only be enabled for component
- // extensions.
- LoadAndExpectError(Manifest(manifest.get(), name),
- errors::kPermissionNotAllowed);
- LoadAndExpectSuccess(Manifest(manifest.get(), name),
- Extension::COMPONENT);
- }
-}
-
TEST_F(ExtensionManifestTest, AllowUnrecognizedPermissions) {
std::string error;
scoped_ptr<DictionaryValue> manifest(
diff --git a/chrome/common/extensions/extension_permission_set.cc b/chrome/common/extensions/extension_permission_set.cc
index 787200e..a805826 100644
--- a/chrome/common/extensions/extension_permission_set.cc
+++ b/chrome/common/extensions/extension_permission_set.cc
@@ -7,10 +7,12 @@
#include <algorithm>
#include <string>
+#include "base/command_line.h"
#include "base/memory/singleton.h"
#include "base/values.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_l10n_util.h"
@@ -21,6 +23,7 @@
#include "net/base/registry_controlled_domain.h"
#include "ui/base/l10n/l10n_util.h"
+namespace ids = extension_misc;
namespace {
// Helper for GetDistinctHosts(): com > net > org > everything else.
@@ -196,19 +199,6 @@ void ExtensionAPIPermission::RegisterAllPermissions(
kUnlimitedStorage, "unlimitedStorage", 0,
ExtensionPermissionMessage::kNone, kFlagCannotBeOptional, kTypeAll);
- // Register hosted app permissions that are also private.
- info->RegisterPermission(
- kChromePrivate, "chromePrivate", 0,
- ExtensionPermissionMessage::kNone, kFlagCannotBeOptional,
- kTypeAll - kTypePlatformApp);
- info->RegisterPermission(
- kChromeAuthPrivate, "chromeAuthPrivate", 0,
- ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeAll - kTypePlatformApp);
- info->RegisterPermission(
- kWebstorePrivate, "webstorePrivate", 0,
- ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeAll - kTypePlatformApp);
// Register hosted and packaged app permissions.
info->RegisterPermission(
@@ -245,9 +235,6 @@ void ExtensionAPIPermission::RegisterAllPermissions(
kInput, "input", 0, ExtensionPermissionMessage::kNone,
kFlagImpliesFullURLAccess, kTypeDefault);
info->RegisterPermission(
- kInputMethodPrivate, "inputMethodPrivate", 0,
- ExtensionPermissionMessage::kNone, kFlagCannotBeOptional, kTypeDefault);
- info->RegisterPermission(
kManagement, "management", IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT,
ExtensionPermissionMessage::kManagement, kFlagNone, kTypeDefault);
info->RegisterPermission(
@@ -262,9 +249,6 @@ void ExtensionAPIPermission::RegisterAllPermissions(
ExtensionPermissionMessage::kTabs, kFlagNone,
kTypeDefault - kTypePlatformApp);
info->RegisterPermission(
- kTerminalPrivate, "terminalPrivate", 0,
- ExtensionPermissionMessage::kNone, kFlagCannotBeOptional, kTypeDefault);
- info->RegisterPermission(
kTts, "tts", 0,
ExtensionPermissionMessage::kNone, kFlagCannotBeOptional, kTypeDefault);
info->RegisterPermission(
@@ -282,32 +266,73 @@ void ExtensionAPIPermission::RegisterAllPermissions(
kWebRequestBlocking, "webRequestBlocking", 0,
ExtensionPermissionMessage::kNone, kFlagNone,
kTypeDefault - kTypePlatformApp);
- info->RegisterPermission(
- kWebSocketProxyPrivate, "webSocketProxyPrivate", 0,
- ExtensionPermissionMessage::kNone, kFlagCannotBeOptional,
- kTypeDefault - kTypePlatformApp);
// Register private permissions.
info->RegisterPermission(
kChromeosInfoPrivate, "chromeosInfoPrivate", 0,
ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeDefault);
+ kFlagComponentOnly_Deprecated | kFlagCannotBeOptional, kTypeDefault);
info->RegisterPermission(
kFileBrowserPrivate, "fileBrowserPrivate", 0,
ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeDefault);
+ kFlagComponentOnly_Deprecated | kFlagCannotBeOptional, kTypeDefault);
info->RegisterPermission(
kMediaPlayerPrivate, "mediaPlayerPrivate", 0,
ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeDefault);
+ kFlagComponentOnly_Deprecated | kFlagCannotBeOptional, kTypeDefault);
info->RegisterPermission(
kMetricsPrivate, "metricsPrivate", 0,
ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeDefault);
+ kFlagComponentOnly_Deprecated | kFlagCannotBeOptional, kTypeDefault);
info->RegisterPermission(
kSystemPrivate, "systemPrivate", 0,
ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeDefault);
+ kFlagComponentOnly_Deprecated | kFlagCannotBeOptional, kTypeDefault);
+
+ ExtensionAPIPermission* chromeAuthPrivate = info->RegisterPermission(
+ kChromeAuthPrivate, "chromeAuthPrivate", 0,
+ ExtensionPermissionMessage::kNone,
+ kFlagCannotBeOptional, kTypeAll - kTypePlatformApp);
+ chromeAuthPrivate->AddToWhitelist(ids::kCloudPrintAppId);
+
+ ExtensionAPIPermission* chromePrivate = info->RegisterPermission(
+ kChromePrivate, "chromePrivate", 0, ExtensionPermissionMessage::kNone,
+ kFlagCannotBeOptional, kTypeAll - kTypePlatformApp);
+ chromePrivate->AddToWhitelist(ids::kCitrixReceiverAppId);
+ chromePrivate->AddToWhitelist(ids::kCitrixReceiverAppBetaId);
+ chromePrivate->AddToWhitelist(ids::kCitrixReceiverAppDevId);
+
+ ExtensionAPIPermission* inputMethodPrivate = info->RegisterPermission(
+ kInputMethodPrivate, "inputMethodPrivate", 0,
+ ExtensionPermissionMessage::kNone, kFlagCannotBeOptional, kTypeDefault);
+ inputMethodPrivate->AddToWhitelist(ids::kCitrixReceiverAppId);
+ inputMethodPrivate->AddToWhitelist(ids::kCitrixReceiverAppBetaId);
+ inputMethodPrivate->AddToWhitelist(ids::kCitrixReceiverAppDevId);
+ inputMethodPrivate->AddToWhitelist(ids::kHTermAppId);
+ inputMethodPrivate->AddToWhitelist(ids::kHTermDevAppId);
+
+ ExtensionAPIPermission* terminalPrivate = info->RegisterPermission(
+ kTerminalPrivate, "terminalPrivate", 0, ExtensionPermissionMessage::kNone,
+ kFlagCannotBeOptional, kTypeDefault);
+ terminalPrivate->AddToWhitelist(ids::kHTermAppId);
+ terminalPrivate->AddToWhitelist(ids::kHTermDevAppId);
+
+ ExtensionAPIPermission* webSocketProxyPrivate = info->RegisterPermission(
+ kWebSocketProxyPrivate, "webSocketProxyPrivate", 0,
+ ExtensionPermissionMessage::kNone,
+ kFlagCannotBeOptional, kTypeDefault - kTypePlatformApp);
+ webSocketProxyPrivate->AddToWhitelist(ids::kCitrixReceiverAppId);
+ webSocketProxyPrivate->AddToWhitelist(ids::kCitrixReceiverAppBetaId);
+ webSocketProxyPrivate->AddToWhitelist(ids::kCitrixReceiverAppDevId);
+ webSocketProxyPrivate->AddToWhitelist(ids::kHTermAppId);
+ webSocketProxyPrivate->AddToWhitelist(ids::kHTermDevAppId);
+
+ ExtensionAPIPermission* webstorePrivate = info->RegisterPermission(
+ kWebstorePrivate, "webstorePrivate", 0,
+ ExtensionPermissionMessage::kNone,
+ kFlagCannotBeOptional, kTypeAll - kTypePlatformApp);
+ webstorePrivate->AddToWhitelist(ids::kEnterpriseWebStoreAppId);
+ webstorePrivate->AddToWhitelist(ids::kWebStoreAppId);
// Full url access permissions.
info->RegisterPermission(
@@ -338,6 +363,25 @@ void ExtensionAPIPermission::RegisterAllPermissions(
info->RegisterAlias("tabs", kWindowsPermission);
}
+bool ExtensionAPIPermission::HasWhitelist() const {
+ return !whitelist_.empty();
+}
+
+bool ExtensionAPIPermission::IsWhitelisted(
+ const std::string& extension_id) const {
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kWhitelistedExtensionID)) {
+ if (extension_id == command_line->GetSwitchValueASCII(
+ switches::kWhitelistedExtensionID))
+ return true;
+ }
+ return whitelist_.find(extension_id) != whitelist_.end();
+}
+
+void ExtensionAPIPermission::AddToWhitelist(const std::string& extension_id) {
+ whitelist_.insert(extension_id);
+}
+
//
// ExtensionPermissionsInfo
//
@@ -395,7 +439,7 @@ void ExtensionPermissionsInfo::RegisterAlias(
name_map_[alias] = name_map_[name];
}
-void ExtensionPermissionsInfo::RegisterPermission(
+ExtensionAPIPermission* ExtensionPermissionsInfo::RegisterPermission(
ExtensionAPIPermission::ID id,
const char* name,
int l10n_message_id,
@@ -412,6 +456,8 @@ void ExtensionPermissionsInfo::RegisterPermission(
name_map_[name] = permission;
permission_count_++;
+
+ return permission;
}
//
diff --git a/chrome/common/extensions/extension_permission_set.h b/chrome/common/extensions/extension_permission_set.h
index b56d12ed..99046e1 100644
--- a/chrome/common/extensions/extension_permission_set.h
+++ b/chrome/common/extensions/extension_permission_set.h
@@ -18,6 +18,8 @@
#include "base/string16.h"
#include "chrome/common/extensions/url_pattern_set.h"
+// TODO(jstritar): Move each class to its own file in extensions/permissions.
+
class Extension;
class ExtensionPermissionsInfo;
@@ -146,10 +148,11 @@ class ExtensionAPIPermission {
kFlagImpliesFullURLAccess = 1 << 1,
// Indicates that the permission is private to COMPONENT extensions.
- kFlagComponentOnly = 1 << 2,
+ // Depcrecated: please use the whitelist.
+ kFlagComponentOnly_Deprecated = 1 << 2,
// Indicates that extensions cannot specify the permission as optional.
- kFlagCannotBeOptional = 1 << 3,
+ kFlagCannotBeOptional = 1 << 3
};
// Flags for specifying what extension types can use the permission.
@@ -209,9 +212,16 @@ class ExtensionAPIPermission {
// Returns true if this permission can only be acquired by COMPONENT
// extensions.
bool is_component_only() const {
- return (flags_ & kFlagComponentOnly) != 0;
+ return (flags_ & kFlagComponentOnly_Deprecated) != 0;
}
+ // Returns true if access to this permission is restricted by a whitelist.
+ bool HasWhitelist() const;
+
+ // Returns true if |extension_id| is whitelisted. The return value is only
+ // relevant if this permission has a whitelist.
+ bool IsWhitelisted(const std::string& extension_id) const;
+
// Returns true if regular extensions can specify this permission.
bool supports_extensions() const {
return (type_restrictions_ & kTypeExtension) != 0;
@@ -250,6 +260,8 @@ class ExtensionAPIPermission {
// Register ALL the permissions!
static void RegisterAllPermissions(ExtensionPermissionsInfo* info);
+ typedef std::set<std::string> ExtensionWhitelist;
+
explicit ExtensionAPIPermission(
ID id,
const char* name,
@@ -258,12 +270,16 @@ class ExtensionAPIPermission {
int flags,
int type_restrictions);
+ // Adds |extension_id| to the whitelist for this permission.
+ void AddToWhitelist(const std::string& extension_id);
+
ID id_;
const char* name_;
int flags_;
int type_restrictions_;
int l10n_message_id_;
ExtensionPermissionMessage::ID message_id_;
+ ExtensionWhitelist whitelist_;
};
typedef std::set<ExtensionAPIPermission::ID> ExtensionAPIPermissionSet;
@@ -302,7 +318,7 @@ class ExtensionPermissionsInfo {
void RegisterAlias(const char* name, const char* alias);
// Registers a permission with the specified attributes and flags.
- void RegisterPermission(
+ ExtensionAPIPermission* RegisterPermission(
ExtensionAPIPermission::ID id,
const char* name,
int l10n_message_id,
@@ -435,7 +451,7 @@ class ExtensionPermissionSet
const URLPatternSet& scriptable_hosts() const { return scriptable_hosts_; }
private:
- FRIEND_TEST_ALL_PREFIXES(ExtensionPermissionSetTest,
+ FRIEND_TEST_ALL_PREFIXES(ExtensionPermissionsTest,
HasLessHostPrivilegesThan);
friend class base::RefCountedThreadSafe<ExtensionPermissionSet>;
diff --git a/chrome/common/extensions/extension_permission_set_unittest.cc b/chrome/common/extensions/extension_permission_set_unittest.cc
index 0267bf6..782146f 100644
--- a/chrome/common/extensions/extension_permission_set_unittest.cc
+++ b/chrome/common/extensions/extension_permission_set_unittest.cc
@@ -10,8 +10,14 @@
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/extension_error_utils.h"
+#include "chrome/common/extensions/extension_permission_set.h"
#include "testing/gtest/include/gtest/gtest.h"
+namespace errors = extension_manifest_errors;
+namespace keys = extension_manifest_keys;
+namespace values = extension_manifest_values;
namespace {
static scoped_refptr<Extension> LoadManifest(const std::string& dir,
@@ -44,6 +50,27 @@ static scoped_refptr<Extension> LoadManifest(const std::string& dir,
return LoadManifest(dir, test_file, Extension::NO_FLAGS);
}
+static scoped_refptr<Extension> LoadManifestFromValue(
+ DictionaryValue* manifest,
+ Extension::Location location,
+ std::string* error) {
+ return Extension::Create(FilePath(), location, *manifest,
+ Extension::STRICT_ERROR_CHECKS, error);
+}
+
+static void LoadManifestAndExpectError(DictionaryValue* manifest,
+ Extension::Location location,
+ const std::string& permission) {
+ std::string error;
+ scoped_refptr<Extension> extension =
+ LoadManifestFromValue(manifest, location, &error);
+
+ std::string expected_error = ExtensionErrorUtils::FormatErrorMessage(
+ errors::kPermissionNotAllowed, permission);
+ EXPECT_FALSE(extension);
+ EXPECT_EQ(expected_error, error);
+}
+
void CompareLists(const std::vector<std::string>& expected,
const std::vector<std::string>& actual) {
ASSERT_EQ(expected.size(), actual.size());
@@ -60,15 +87,11 @@ static void AddPattern(URLPatternSet* extent, const std::string& pattern) {
} // namespace
-class ExtensionAPIPermissionTest : public testing::Test {
+class ExtensionPermissionsTest : public testing::Test {
};
-class ExtensionPermissionSetTest : public testing::Test {
-};
-
-
// Tests GetByID.
-TEST(ExtensionPermissionsInfoTest, GetByID) {
+TEST(ExtensionPermissionsTest, GetByID) {
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
ExtensionAPIPermissionSet ids = info->GetAll();
for (ExtensionAPIPermissionSet::iterator i = ids.begin();
@@ -78,7 +101,7 @@ TEST(ExtensionPermissionsInfoTest, GetByID) {
}
// Tests that GetByName works with normal permission names and aliases.
-TEST(ExtensionPermissionsInfoTest, GetByName) {
+TEST(ExtensionPermissionsTest, GetByName) {
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
EXPECT_EQ(ExtensionAPIPermission::kTab, info->GetByName("tabs")->id());
EXPECT_EQ(ExtensionAPIPermission::kManagement,
@@ -86,7 +109,7 @@ TEST(ExtensionPermissionsInfoTest, GetByName) {
EXPECT_FALSE(info->GetByName("alsdkfjasldkfj"));
}
-TEST(ExtensionPermissionsInfoTest, GetAll) {
+TEST(ExtensionPermissionsTest, GetAll) {
size_t count = 0;
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
ExtensionAPIPermissionSet apis = info->GetAll();
@@ -100,7 +123,7 @@ TEST(ExtensionPermissionsInfoTest, GetAll) {
EXPECT_EQ(count, info->get_permission_count());
}
-TEST(ExtensionPermissionInfoTest, GetAllByName) {
+TEST(ExtensionPermissionsTest, GetAllByName) {
std::set<std::string> names;
names.insert("background");
names.insert("management");
@@ -121,7 +144,7 @@ TEST(ExtensionPermissionInfoTest, GetAllByName) {
}
// Tests that the aliases are properly mapped.
-TEST(ExtensionAPIPermissionTest, Aliases) {
+TEST(ExtensionPermissionsTest, Aliases) {
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
// tabs: tabs, windows
std::string tabs_name = "tabs";
@@ -139,7 +162,7 @@ TEST(ExtensionAPIPermissionTest, Aliases) {
info->GetByName("unlimited_storage")->id());
}
-TEST(ExtensionAPIPermissionTest, HostedAppPermissions) {
+TEST(ExtensionPermissionsTest, HostedAppPermissions) {
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
ExtensionAPIPermissionSet hosted_perms;
hosted_perms.insert(ExtensionAPIPermission::kAppNotifications);
@@ -154,19 +177,41 @@ TEST(ExtensionAPIPermissionTest, HostedAppPermissions) {
hosted_perms.insert(ExtensionAPIPermission::kUnlimitedStorage);
hosted_perms.insert(ExtensionAPIPermission::kWebstorePrivate);
+ DictionaryValue source;
+ source.SetString(keys::kName, "permission hosted app test");
+ source.SetString(keys::kVersion, "1");
+ source.SetInteger(keys::kManifestVersion, 2);
+ ListValue* urls = new ListValue();
+ urls->Append(Value::CreateStringValue("http://localhost/test.html"));
+ source.Set(keys::kWebURLs, urls);
+ source.SetString(keys::kLaunchWebURL, "http://localhost/test.html");
+
ExtensionAPIPermissionSet perms = info->GetAll();
size_t count = 0;
for (ExtensionAPIPermissionSet::iterator i = perms.begin();
i != perms.end(); ++i) {
- count += hosted_perms.count(*i);
- EXPECT_EQ(hosted_perms.count(*i) > 0,
- info->GetByID(*i)->supports_hosted_apps());
+ ExtensionAPIPermission* permission = info->GetByID(*i);
+ if (permission->supports_hosted_apps()) {
+ count++;
+ EXPECT_TRUE(hosted_perms.count(*i));
+ continue;
+ }
+
+ scoped_ptr<DictionaryValue> manifest(source.DeepCopy());
+ ListValue* permissions = new ListValue();
+ permissions->Append(Value::CreateStringValue(permission->name()));
+ manifest->Set(keys::kPermissions, permissions);
+
+ // This error may be generated for other reasons too, like if the permission
+ // has a whitelist.
+ LoadManifestAndExpectError(
+ manifest.get(), Extension::INTERNAL, permission->name());
}
EXPECT_EQ(hosted_perms.size(), count);
}
-TEST(ExtensionAPIPermissionTest, PlatformAppPermissions) {
+TEST(ExtensionPermissionsTest, PlatformAppPermissions) {
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
ExtensionAPIPermissionSet blacklist;
blacklist.insert(ExtensionAPIPermission::kAppNotifications);
@@ -180,42 +225,125 @@ TEST(ExtensionAPIPermissionTest, PlatformAppPermissions) {
blacklist.insert(ExtensionAPIPermission::kWebSocketProxyPrivate);
blacklist.insert(ExtensionAPIPermission::kWebstorePrivate);
+ DictionaryValue source;
+ source.SetString(keys::kName, "permission platform app test");
+ source.SetString(keys::kVersion, "1");
+ source.SetInteger(keys::kManifestVersion, 2);
+ source.SetBoolean(keys::kPlatformApp, true);
+ source.SetString(keys::kLaunchLocalPath, "test.html");
+ source.SetString(keys::kLaunchContainer, values::kLaunchContainerShell);
+
ExtensionAPIPermissionSet perms = info->GetAll();
size_t count = 0;
for (ExtensionAPIPermissionSet::iterator i = perms.begin();
i != perms.end(); ++i) {
- count += blacklist.count(*i);
- EXPECT_EQ(blacklist.count(*i) > 0,
- !info->GetByID(*i)->supports_platform_apps());
+ ExtensionAPIPermission* permission = info->GetByID(*i);
+ if (permission->supports_platform_apps())
+ continue;
+
+ count++;
+ EXPECT_TRUE(blacklist.count(*i));
+
+ scoped_ptr<DictionaryValue> manifest(source.DeepCopy());
+ ListValue* permissions = new ListValue();
+ permissions->Append(Value::CreateStringValue(permission->name()));
+ manifest->Set(keys::kPermissions, permissions);
+
+ // This error may be generated for other reasons too, like if the permission
+ // has a whitelist.
+ LoadManifestAndExpectError(
+ manifest.get(), Extension::INTERNAL, permission->name());
}
EXPECT_EQ(blacklist.size(), count);
}
-TEST(ExtensionAPIPermissionTest, ComponentOnlyPermissions) {
+TEST(ExtensionPermissionsTest, ComponentOnlyPermissions) {
ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
ExtensionAPIPermissionSet private_perms;
- private_perms.insert(ExtensionAPIPermission::kChromeAuthPrivate);
private_perms.insert(ExtensionAPIPermission::kChromeosInfoPrivate);
private_perms.insert(ExtensionAPIPermission::kFileBrowserPrivate);
private_perms.insert(ExtensionAPIPermission::kMediaPlayerPrivate);
private_perms.insert(ExtensionAPIPermission::kMetricsPrivate);
private_perms.insert(ExtensionAPIPermission::kSystemPrivate);
- private_perms.insert(ExtensionAPIPermission::kWebstorePrivate);
+
+ DictionaryValue source;
+ source.SetString(keys::kName, "component only permission test");
+ source.SetString(keys::kVersion, "1");
+ source.SetInteger(keys::kManifestVersion, 2);
ExtensionAPIPermissionSet perms = info->GetAll();
- int count = 0;
+ size_t count = 0;
for (ExtensionAPIPermissionSet::iterator i = perms.begin();
i != perms.end(); ++i) {
- count += private_perms.count(*i);
- EXPECT_EQ(private_perms.count(*i) > 0,
- info->GetByID(*i)->is_component_only());
+ ExtensionAPIPermission* permission = info->GetByID(*i);
+
+ scoped_ptr<DictionaryValue> manifest(source.DeepCopy());
+ ListValue* permissions = new ListValue();
+ permissions->Append(Value::CreateStringValue(permission->name()));
+ manifest->Set(keys::kPermissions, permissions);
+
+ // COMPONENT extensions can access any permission.
+ std::string error;
+ scoped_refptr<Extension> extension = LoadManifestFromValue(
+ manifest.get(), Extension::COMPONENT, &error);
+ EXPECT_TRUE(extension);
+
+ if (!permission->is_component_only())
+ continue;
+
+ count++;
+ EXPECT_TRUE(private_perms.count(*i));
+
+ // But INTERNAL extensions can't access component only permissions.
+ LoadManifestAndExpectError(
+ manifest.get(), Extension::INTERNAL, permission->name());
+ }
+
+ EXPECT_EQ(private_perms.size(), count);
+}
+
+// Tests that permission whitelists are enforced.
+TEST(ExtensionPermissionsTest, Whitelists) {
+ ExtensionPermissionsInfo* info = ExtensionPermissionsInfo::GetInstance();
+ ExtensionAPIPermissionSet ids = info->GetAll();
+
+ ExtensionAPIPermissionSet expected_whitelists;
+ expected_whitelists.insert(ExtensionAPIPermission::kChromeAuthPrivate);
+ expected_whitelists.insert(ExtensionAPIPermission::kChromePrivate);
+ expected_whitelists.insert(ExtensionAPIPermission::kInputMethodPrivate);
+ expected_whitelists.insert(ExtensionAPIPermission::kTerminalPrivate);
+ expected_whitelists.insert(ExtensionAPIPermission::kWebSocketProxyPrivate);
+ expected_whitelists.insert(ExtensionAPIPermission::kWebstorePrivate);
+
+ DictionaryValue source;
+ source.SetString(keys::kName, "permission whitelist test");
+ source.SetString(keys::kVersion, "1");
+ source.SetInteger(keys::kManifestVersion, 2);
+
+ size_t whitelists = 0;
+ for (ExtensionAPIPermissionSet::iterator i = ids.begin();
+ i != ids.end(); ++i) {
+ ExtensionAPIPermission* permission = info->GetByID(*i);
+ if (!permission->HasWhitelist())
+ continue;
+
+ whitelists++;
+ EXPECT_TRUE(expected_whitelists.count(*i));
+
+ scoped_ptr<DictionaryValue> manifest(source.DeepCopy());
+ ListValue* permissions = new ListValue();
+ permissions->Append(Value::CreateStringValue(permission->name()));
+ manifest->Set(keys::kPermissions, permissions);
+
+ LoadManifestAndExpectError(
+ manifest.get(), Extension::INTERNAL, permission->name());
}
- EXPECT_EQ(7, count);
+ EXPECT_EQ(expected_whitelists.size(), whitelists);
}
-TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
+TEST(ExtensionPermissionsTest, EffectiveHostPermissions) {
scoped_refptr<Extension> extension;
scoped_refptr<const ExtensionPermissionSet> permissions;
@@ -291,7 +419,7 @@ TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
EXPECT_TRUE(permissions->HasEffectiveAccessToAllHosts());
}
-TEST(ExtensionPermissionSetTest, ExplicitAccessToOrigin) {
+TEST(ExtensionPermissionsTest, ExplicitAccessToOrigin) {
ExtensionAPIPermissionSet apis;
URLPatternSet explicit_hosts;
URLPatternSet scriptable_hosts;
@@ -314,7 +442,7 @@ TEST(ExtensionPermissionSetTest, ExplicitAccessToOrigin) {
GURL("http://test.example.com")));
}
-TEST(ExtensionPermissionSetTest, CreateUnion) {
+TEST(ExtensionPermissionsTest, CreateUnion) {
ExtensionAPIPermissionSet apis1;
ExtensionAPIPermissionSet apis2;
ExtensionAPIPermissionSet expected_apis;
@@ -395,7 +523,7 @@ TEST(ExtensionPermissionSetTest, CreateUnion) {
EXPECT_EQ(effective_hosts, union_set->effective_hosts());
}
-TEST(ExtensionPermissionSetTest, CreateIntersection) {
+TEST(ExtensionPermissionsTest, CreateIntersection) {
ExtensionAPIPermissionSet apis1;
ExtensionAPIPermissionSet apis2;
ExtensionAPIPermissionSet expected_apis;
@@ -471,7 +599,7 @@ TEST(ExtensionPermissionSetTest, CreateIntersection) {
EXPECT_EQ(effective_hosts, new_set->effective_hosts());
}
-TEST(ExtensionPermissionSetTest, CreateDifference) {
+TEST(ExtensionPermissionsTest, CreateDifference) {
ExtensionAPIPermissionSet apis1;
ExtensionAPIPermissionSet apis2;
ExtensionAPIPermissionSet expected_apis;
@@ -535,7 +663,7 @@ TEST(ExtensionPermissionSetTest, CreateDifference) {
EXPECT_TRUE(set1->IsEmpty());
}
-TEST(ExtensionPermissionSetTest, HasLessPrivilegesThan) {
+TEST(ExtensionPermissionsTest, HasLessPrivilegesThan) {
const struct {
const char* base_name;
// Increase these sizes if you have more than 10.
@@ -628,7 +756,7 @@ TEST(ExtensionPermissionSetTest, HasLessPrivilegesThan) {
}
}
-TEST(ExtensionPermissionSetTest, PermissionMessages) {
+TEST(ExtensionPermissionsTest, PermissionMessages) {
// Ensure that all permissions that needs to show install UI actually have
// strings associated with them.
ExtensionAPIPermissionSet skip;
@@ -702,7 +830,7 @@ TEST(ExtensionPermissionSetTest, PermissionMessages) {
}
// Tests the default permissions (empty API permission set).
-TEST(ExtensionPermissionSetTest, DefaultFunctionAccess) {
+TEST(ExtensionPermissionsTest, DefaultFunctionAccess) {
const struct {
const char* permission_name;
bool expect_success;
@@ -770,7 +898,7 @@ TEST(ExtensionPermissionSetTest, DefaultAnyAPIAccess) {
}
}
-TEST(ExtensionPermissionSetTest, GetWarningMessages_ManyHosts) {
+TEST(ExtensionPermissionsTest, GetWarningMessages_ManyHosts) {
scoped_refptr<Extension> extension;
extension = LoadManifest("permissions", "many-hosts.json");
@@ -781,7 +909,7 @@ TEST(ExtensionPermissionSetTest, GetWarningMessages_ManyHosts) {
UTF16ToUTF8(warnings[0]));
}
-TEST(ExtensionPermissionSetTest, GetWarningMessages_Plugins) {
+TEST(ExtensionPermissionsTest, GetWarningMessages_Plugins) {
scoped_refptr<Extension> extension;
scoped_refptr<ExtensionPermissionSet> permissions;
@@ -799,7 +927,7 @@ TEST(ExtensionPermissionSetTest, GetWarningMessages_Plugins) {
#endif
}
-TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
+TEST(ExtensionPermissionsTest, GetDistinctHostsForDisplay) {
scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
std::set<std::string> expected;
@@ -955,7 +1083,7 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay) {
}
}
-TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_ComIsBestRcd) {
+TEST(ExtensionPermissionsTest, GetDistinctHostsForDisplay_ComIsBestRcd) {
scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
URLPatternSet explicit_hosts;
@@ -980,7 +1108,7 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_ComIsBestRcd) {
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
-TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_NetIs2ndBestRcd) {
+TEST(ExtensionPermissionsTest, GetDistinctHostsForDisplay_NetIs2ndBestRcd) {
scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
URLPatternSet explicit_hosts;
@@ -1004,7 +1132,7 @@ TEST(ExtensionPermissionSetTest, GetDistinctHostsForDisplay_NetIs2ndBestRcd) {
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
-TEST(ExtensionPermissionSetTest,
+TEST(ExtensionPermissionsTest,
GetDistinctHostsForDisplay_OrgIs3rdBestRcd) {
scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
@@ -1028,7 +1156,7 @@ TEST(ExtensionPermissionSetTest,
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
-TEST(ExtensionPermissionSetTest,
+TEST(ExtensionPermissionsTest,
GetDistinctHostsForDisplay_FirstInListIs4thBestRcd) {
scoped_refptr<ExtensionPermissionSet> perm_set;
ExtensionAPIPermissionSet empty_perms;
@@ -1051,7 +1179,7 @@ TEST(ExtensionPermissionSetTest,
EXPECT_EQ(expected, perm_set->GetDistinctHostsForDisplay());
}
-TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
+TEST(ExtensionPermissionsTest, HasLessHostPrivilegesThan) {
URLPatternSet elist1;
URLPatternSet elist2;
URLPatternSet slist1;
@@ -1120,7 +1248,7 @@ TEST(ExtensionPermissionSetTest, HasLessHostPrivilegesThan) {
EXPECT_TRUE(set2->HasLessHostPrivilegesThan(set1.get()));
}
-TEST(ExtensionPermissionSetTest, GetAPIsAsStrings) {
+TEST(ExtensionPermissionsTest, GetAPIsAsStrings) {
ExtensionAPIPermissionSet apis;
URLPatternSet empty_set;
@@ -1140,7 +1268,7 @@ TEST(ExtensionPermissionSetTest, GetAPIsAsStrings) {
ExtensionPermissionsInfo::GetInstance()->GetAllByName(api_names));
}
-TEST(ExtensionPermissionSetTest, IsEmpty) {
+TEST(ExtensionPermissionsTest, IsEmpty) {
ExtensionAPIPermissionSet empty_apis;
URLPatternSet empty_extent;
diff --git a/chrome/renderer/extensions/chrome_private_custom_bindings.cc b/chrome/renderer/extensions/chrome_private_custom_bindings.cc
index 223f197..a1e4fbb 100644
--- a/chrome/renderer/extensions/chrome_private_custom_bindings.cc
+++ b/chrome/renderer/extensions/chrome_private_custom_bindings.cc
@@ -31,25 +31,12 @@ ChromePrivateCustomBindings::ChromePrivateCustomBindings(
// static
v8::Handle<v8::Value> ChromePrivateCustomBindings::DecodeJPEG(
const v8::Arguments& args) {
- static const char* kAllowedIds[] = {
- "haiffjcadagjlijoggckpgfnoeiflnem",
- "gnedhmakppccajfpfiihfcdlnpgomkcf",
- "fjcibdnjlbfnbfdjneajpipnlcppleek",
- "oflbaaikkabfdfkimeclgkackhdkpnip" // Testing extension.
- };
- const std::vector<std::string> allowed_ids(
- kAllowedIds, kAllowedIds + arraysize(kAllowedIds));
-
ChromePrivateCustomBindings* v8_extension =
GetFromArguments<ChromePrivateCustomBindings>(args);
const ::Extension* extension =
v8_extension->GetExtensionForCurrentRenderView();
if (!extension)
return v8::Undefined();
- if (allowed_ids.end() == std::find(
- allowed_ids.begin(), allowed_ids.end(), extension->id())) {
- return v8::Undefined();
- }
DCHECK(args.Length() == 1);
DCHECK(args[0]->IsArray());
diff --git a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/background.html b/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/background.html
deleted file mode 100644
index d9fc1c8..0000000
--- a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/background.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!--
- * Copyright (c) 2011 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.
--->
-<script src="cloud_print_exception.js"></script>
diff --git a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/cloud_print_exception.js b/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/cloud_print_exception.js
deleted file mode 100644
index 56aef5b..0000000
--- a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/cloud_print_exception.js
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2011 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.
-
-// This test is invoked from a non-component app. So this call should throw an
-// exception when we try and access the chromeAuthPrivate API.
-var tests = [
- function exceptionSetCreds() {
- var expectedException =
- "Error: You do not have permission to use " +
- "'chromeAuthPrivate.setCloudPrintCredentials'. Be sure to declare in " +
- "your manifest what permissions you need.";
- var userEmail = 'foo@gmail.com';
- var robotEmail = 'foorobot@googleusercontent.com';
- var credentials = '1/23546efa54';
- try {
- chrome.chromeAuthPrivate.setCloudPrintCredentials(
- userEmail, robotEmail, credentials);
- } catch (err) {
- chrome.test.assertEq(expectedException, err.toString());
- chrome.test.succeed();
- return;
- }
- chrome.test.fail();
- }
-];
-
-chrome.test.runTests(tests);
diff --git a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/manifest.json b/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/manifest.json
deleted file mode 100644
index 50d9768..0000000
--- a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_app/manifest.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "Cloud Print Installed App",
- "version": "0.1",
- "manifest_version": 2,
- "description": "Cloud Print Installed App Test For Failure",
- "background": {
- "page": "background.html"
- },
- "permissions": [
- "chromeAuthPrivate"
- ]
-}
diff --git a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/background.html b/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/background.html
deleted file mode 100644
index 5c94fc4..0000000
--- a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/background.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!--
- * Copyright (c) 2011 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.
--->
-<script src="cloud_print_fail.js"></script>
diff --git a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/cloud_print_fail.js b/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/cloud_print_fail.js
deleted file mode 100644
index c5db1102b6..0000000
--- a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/cloud_print_fail.js
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011 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.
-
-// This test is invoked from an installed component app. Since we have an
-// explicit URL check in the API, this should fail.
-var tests = [
- function failureSetCreds() {
- var expectedError = "Cannot call this API from a non-cloudprint URL."
- var userEmail = 'foo@gmail.com';
- var robotEmail = 'foorobot@googleusercontent.com';
- var credentials = '1/23546efa54';
- chrome.chromeAuthPrivate.setCloudPrintCredentials(
- userEmail, robotEmail, credentials,
- chrome.test.callbackFail(expectedError));
- }
-];
-
-chrome.test.runTests(tests);
diff --git a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/manifest.json b/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/manifest.json
deleted file mode 100644
index 4e32220..0000000
--- a/chrome/test/data/extensions/api_test/chrome_auth_private/installed_component_app/manifest.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp40PYAXfSDlzCW1f5MDzRW64h0YhgV7MX8Frem0vO1ZAlq/mlUO4KxwkF2AZliFScO4Cc3CYpO6jpHXwz27tUwaN46C/LzYO7u/kb2piOep8gClvZ64EMnDv5PIoIeZlOJhkpnfs/5FbQt5sqT9avXX7YfLCLBJBql0U/V5615wIDAQAB",
- "name": "Cloud Print Installed Component App",
- "version": "0.1",
- "manifest_version": 2,
- "description": "Cloud Print App Test For Failure",
- "background": {
- "page": "background.html"
- },
- "permissions": [
- "chromeAuthPrivate"
- ]
-}
diff --git a/chrome/test/data/extensions/api_test/terminal/component_extension/background.html b/chrome/test/data/extensions/api_test/terminal/component_extension/background.html
deleted file mode 100644
index 8d32ce8..0000000
--- a/chrome/test/data/extensions/api_test/terminal/component_extension/background.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<script>
-chrome.tabs.create({
- url: "test.html"
-});
-</script>
diff --git a/chrome/test/data/extensions/api_test/terminal/component_extension/manifest.json b/chrome/test/data/extensions/api_test/terminal/component_extension/manifest.json
index aa036e7..629c551 100644
--- a/chrome/test/data/extensions/api_test/terminal/component_extension/manifest.json
+++ b/chrome/test/data/extensions/api_test/terminal/component_extension/manifest.json
@@ -3,8 +3,5 @@
"name": "chrome.terminalPrivate.apitest",
"version": "0.1",
"description": "end-to-end test for terminalPrivate api. Test opens two crosh processes, starts infinite loop that echos 'aaaa' in both of them and observes output.",
- "background": {
- "page": "background.html"
- },
"permissions": ["terminalPrivate"]
}
diff --git a/chrome/test/data/extensions/api_test/terminal/no_permission/manifest.json b/chrome/test/data/extensions/api_test/terminal/no_permission/manifest.json
deleted file mode 100644
index 812f991..0000000
--- a/chrome/test/data/extensions/api_test/terminal/no_permission/manifest.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "name": "chrome.terminalPrivate.apitest.permissions",
- "version": "0.1",
- "description": "Test that non-component extension cannot use the terminalPrivateApi.",
- "background": {
- "scripts": ["test.js"]
- },
- "permissions": ["terminalPrivate"]
-}
diff --git a/chrome/test/data/extensions/api_test/terminal/no_permission/test.js b/chrome/test/data/extensions/api_test/terminal/no_permission/test.js
deleted file mode 100644
index a8c5389..0000000
--- a/chrome/test/data/extensions/api_test/terminal/no_permission/test.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 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.
-
-var kPermissionError = "Extension does not have the permission to use this API";
-
-chrome.test.runTests([
- function tryOpenExtension() {
- chrome.terminalPrivate.openTerminalProcess("crosh",
- chrome.test.callbackFail(kPermissionError));
- },
- function trySendInput() {
- chrome.terminalPrivate.sendInput(1222, "some input",
- chrome.test.callbackFail(kPermissionError));
- },
- function tryClose() {
- chrome.terminalPrivate.closeTerminalProcess(1222,
- chrome.test.callbackFail(kPermissionError));
- }
-]);