summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authortbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-25 01:19:34 +0000
committertbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-25 01:19:34 +0000
commit921c31cb9c0dc0c83cc072c302ecec5338f57c94 (patch)
treef4c0ff0e66b6e8138b9902ca98a471049030f0a8 /chrome
parent26aa78079d15a2b553294d02432faf8a544be204 (diff)
downloadchromium_src-921c31cb9c0dc0c83cc072c302ecec5338f57c94.zip
chromium_src-921c31cb9c0dc0c83cc072c302ecec5338f57c94.tar.gz
chromium_src-921c31cb9c0dc0c83cc072c302ecec5338f57c94.tar.bz2
Setup permissions for terminalPrivateApi.
Access to terminalPrivateApi will be allowed to component and hterm extensions only. Hterm extension is not component extension, so restricting access to component extensions only won't work. (Hterm already has access to webSocketPrivate API, and extension ID are copied from there) Also, add "exit" to allowed process output event types (this event will be dispatched when we detect a observed process has died). BUG=chromium-os:23273 TEST=ExtensionTerminalPrivateApiTest.* Review URL: https://chromiumcodereview.appspot.com/9150051 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118967 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/extensions/api/terminal/terminal_private_api.cc65
-rw-r--r--chrome/browser/extensions/api/terminal/terminal_private_api.h28
-rw-r--r--chrome/browser/extensions/api/terminal/terminal_private_apitest.cc8
-rw-r--r--chrome/browser/extensions/extension_event_names.cc3
-rw-r--r--chrome/browser/extensions/extension_event_names.h3
-rw-r--r--chrome/common/extensions/extension_permission_set.cc7
-rw-r--r--chrome/common/extensions/extension_permission_set_unittest.cc3
-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
9 files changed, 122 insertions, 24 deletions
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index e555518..be76747 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_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.
@@ -9,7 +9,9 @@
#include "base/values.h"
#include "chrome/browser/chromeos/process_proxy/process_proxy_registry.h"
#include "chrome/browser/chromeos/system/runtime_environment.h"
+#include "chrome/browser/extensions/extension_event_names.h"
#include "chrome/browser/extensions/extension_event_router.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
@@ -20,6 +22,32 @@ 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;
@@ -36,15 +64,19 @@ const char* GetProcessCommandForName(const std::string& name) {
}
void NotifyProcessOutput(Profile* profile,
+ const std::string& extension_id,
pid_t pid,
const std::string& output_type,
const std::string& output) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessOutput, profile, pid, output_type, output));
+ base::Bind(&NotifyProcessOutput, profile, extension_id,
+ pid, output_type, output));
return;
}
+ CHECK(AllowAccessToExtension(profile, extension_id));
+
base::ListValue args;
args.Append(new base::FundamentalValue(pid));
args.Append(new base::StringValue(output_type));
@@ -53,22 +85,37 @@ void NotifyProcessOutput(Profile* profile,
std::string args_json;
base::JSONWriter::Write(&args, false /* pretty_print */, &args_json);
- // TODO(tbarzic): Send event only to the renderer that runs process pid.
if (profile && profile->GetExtensionEventRouter()) {
- profile->GetExtensionEventRouter()->DispatchEventToRenderers(
- "terminalPrivate.onProcessOutput", args_json, NULL, GURL());
+ profile->GetExtensionEventRouter()->DispatchEventToExtension(
+ extension_id, extension_event_names::kOnTerminalProcessOutput,
+ args_json, NULL, GURL());
}
}
} // namespace
+TerminalPrivateFunction::TerminalPrivateFunction() {
+}
+
+TerminalPrivateFunction::~TerminalPrivateFunction() {
+}
+
+bool TerminalPrivateFunction::RunImpl() {
+ if (!AllowAccessToExtension(profile_, extension_id())) {
+ error_ = kPermissionError;
+ return false;
+ }
+
+ return RunTerminalFunction();
+}
+
OpenTerminalProcessFunction::OpenTerminalProcessFunction() : command_(NULL) {
}
OpenTerminalProcessFunction::~OpenTerminalProcessFunction() {
}
-bool OpenTerminalProcessFunction::RunImpl() {
+bool OpenTerminalProcessFunction::RunTerminalFunction() {
if (args_->GetSize() != 1)
return false;
@@ -94,7 +141,7 @@ void OpenTerminalProcessFunction::OpenOnFileThread() {
ProcessProxyRegistry* registry = ProcessProxyRegistry::Get();
pid_t pid;
if (!registry->OpenProcess(command_, &pid,
- base::Bind(&NotifyProcessOutput, profile_))) {
+ base::Bind(&NotifyProcessOutput, profile_, extension_id()))) {
// If new process could not be opened, we return -1.
pid = -1;
}
@@ -108,7 +155,7 @@ void OpenTerminalProcessFunction::RespondOnUIThread(pid_t pid) {
SendResponse(true);
}
-bool SendInputToTerminalProcessFunction::RunImpl() {
+bool SendInputToTerminalProcessFunction::RunTerminalFunction() {
if (args_->GetSize() != 2)
return false;
@@ -138,7 +185,7 @@ void SendInputToTerminalProcessFunction::RespondOnUIThread(bool success) {
SendResponse(true);
}
-bool CloseTerminalProcessFunction::RunImpl() {
+bool CloseTerminalProcessFunction::RunTerminalFunction() {
if (args_->GetSize() != 1)
return false;
pid_t pid;
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.h b/chrome/browser/extensions/api/terminal/terminal_private_api.h
index f28fde1..771e94b 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.h
+++ b/chrome/browser/extensions/api/terminal/terminal_private_api.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.
@@ -10,13 +10,27 @@
#include "chrome/browser/extensions/extension_function.h"
+// Base class for all terminalPrivate function classes. Main purpose is to run
+// permission check before calling actual function implementation.
+class TerminalPrivateFunction : public AsyncExtensionFunction {
+ public:
+ TerminalPrivateFunction();
+ virtual ~TerminalPrivateFunction();
+
+ virtual bool RunImpl() OVERRIDE;
+
+ // Override with actual extension function implementation.
+ virtual bool RunTerminalFunction() = 0;
+
+};
+
// Opens new terminal process. Returns the new process id.
-class OpenTerminalProcessFunction : public AsyncExtensionFunction {
+class OpenTerminalProcessFunction : public TerminalPrivateFunction {
public:
OpenTerminalProcessFunction();
virtual ~OpenTerminalProcessFunction();
- virtual bool RunImpl() OVERRIDE;
+ virtual bool RunTerminalFunction() OVERRIDE;
private:
void OpenOnFileThread();
@@ -28,9 +42,9 @@ class OpenTerminalProcessFunction : public AsyncExtensionFunction {
};
// Send input to the terminal process specified by the pid sent as an argument.
-class SendInputToTerminalProcessFunction : public AsyncExtensionFunction {
+class SendInputToTerminalProcessFunction : public TerminalPrivateFunction {
public:
- virtual bool RunImpl() OVERRIDE;
+ virtual bool RunTerminalFunction() OVERRIDE;
private:
void SendInputOnFileThread(pid_t pid, const std::string& input);
@@ -40,9 +54,9 @@ class SendInputToTerminalProcessFunction : public AsyncExtensionFunction {
};
// Closes terminal process with given pid.
-class CloseTerminalProcessFunction : public AsyncExtensionFunction {
+class CloseTerminalProcessFunction : public TerminalPrivateFunction {
public:
- virtual bool RunImpl() OVERRIDE;
+ virtual bool RunTerminalFunction() OVERRIDE;
private:
void CloseOnFileThread(pid_t pid);
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc b/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc
index aab41f9..6497bee 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_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.
@@ -10,4 +10,8 @@ class ExtensionTerminalPrivateApiTest : public ExtensionApiTest {
IN_PROC_BROWSER_TEST_F(ExtensionTerminalPrivateApiTest, TerminalTest) {
EXPECT_TRUE(RunComponentExtensionTest("terminal/component_extension"))
<< message_;
-}
+};
+
+IN_PROC_BROWSER_TEST_F(ExtensionTerminalPrivateApiTest, NoPermission) {
+ EXPECT_TRUE(RunExtensionTest("terminal/no_permission")) << message_;
+};
diff --git a/chrome/browser/extensions/extension_event_names.cc b/chrome/browser/extensions/extension_event_names.cc
index 9291a64..9f25a7a 100644
--- a/chrome/browser/extensions/extension_event_names.cc
+++ b/chrome/browser/extensions/extension_event_names.cc
@@ -39,4 +39,7 @@ const char kOnDownloadChanged[] = "experimental.downloads.onChanged";
const char kOnDownloadErased[] = "experimental.downloads.onErased";
const char kOnSettingsChanged[] = "storage.onChanged";
+
+const char kOnTerminalProcessOutput[] = "terminalPrivate.onProcessOutput";
+
} // namespace extension_event_names
diff --git a/chrome/browser/extensions/extension_event_names.h b/chrome/browser/extensions/extension_event_names.h
index 33e15c9..d18c1f11 100644
--- a/chrome/browser/extensions/extension_event_names.h
+++ b/chrome/browser/extensions/extension_event_names.h
@@ -50,6 +50,9 @@ extern const char kOnDownloadErased[];
// Settings.
extern const char kOnSettingsChanged[];
+// TerminalPrivate.
+extern const char kOnTerminalProcessOutput[];
+
}; // namespace extension_event_names
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_EVENT_NAMES_H_
diff --git a/chrome/common/extensions/extension_permission_set.cc b/chrome/common/extensions/extension_permission_set.cc
index 20a70a9..0303999 100644
--- a/chrome/common/extensions/extension_permission_set.cc
+++ b/chrome/common/extensions/extension_permission_set.cc
@@ -262,6 +262,9 @@ 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(
@@ -305,10 +308,6 @@ void ExtensionAPIPermission::RegisterAllPermissions(
kSystemPrivate, "systemPrivate", 0,
ExtensionPermissionMessage::kNone,
kFlagComponentOnly | kFlagCannotBeOptional, kTypeDefault);
- info->RegisterPermission(
- kTerminalPrivate, "terminalPrivate", 0,
- ExtensionPermissionMessage::kNone,
- kFlagComponentOnly | kFlagCannotBeOptional, kTypeDefault);
// Full url access permissions.
info->RegisterPermission(
diff --git a/chrome/common/extensions/extension_permission_set_unittest.cc b/chrome/common/extensions/extension_permission_set_unittest.cc
index 7e6d3a2..3b20fe5 100644
--- a/chrome/common/extensions/extension_permission_set_unittest.cc
+++ b/chrome/common/extensions/extension_permission_set_unittest.cc
@@ -201,7 +201,6 @@ TEST(ExtensionAPIPermissionTest, ComponentOnlyPermissions) {
private_perms.insert(ExtensionAPIPermission::kMediaPlayerPrivate);
private_perms.insert(ExtensionAPIPermission::kMetricsPrivate);
private_perms.insert(ExtensionAPIPermission::kSystemPrivate);
- private_perms.insert(ExtensionAPIPermission::kTerminalPrivate);
private_perms.insert(ExtensionAPIPermission::kWebstorePrivate);
ExtensionAPIPermissionSet perms = info->GetAll();
@@ -213,7 +212,7 @@ TEST(ExtensionAPIPermissionTest, ComponentOnlyPermissions) {
info->GetByID(*i)->is_component_only());
}
- EXPECT_EQ(8, count);
+ EXPECT_EQ(7, count);
}
TEST(ExtensionPermissionSetTest, EffectiveHostPermissions) {
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
new file mode 100644
index 0000000..812f991
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/terminal/no_permission/manifest.json
@@ -0,0 +1,9 @@
+{
+ "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
new file mode 100644
index 0000000..a8c5389
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/terminal/no_permission/test.js
@@ -0,0 +1,20 @@
+// 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));
+ }
+]);