Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(468)

Side by Side Diff: chrome/renderer/extensions/extension_process_bindings.cc

Issue 164039: Add module-level permissions to extensions. (Closed)
Patch Set: final nits Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/extensions/extension_process_bindings.h" 5 #include "chrome/renderer/extensions/extension_process_bindings.h"
6 6
7 #include "base/singleton.h" 7 #include "base/singleton.h"
8 #include "chrome/common/extensions/extension.h"
8 #include "chrome/common/render_messages.h" 9 #include "chrome/common/render_messages.h"
9 #include "chrome/common/url_constants.h" 10 #include "chrome/common/url_constants.h"
10 #include "chrome/renderer/extensions/bindings_utils.h" 11 #include "chrome/renderer/extensions/bindings_utils.h"
11 #include "chrome/renderer/extensions/event_bindings.h" 12 #include "chrome/renderer/extensions/event_bindings.h"
12 #include "chrome/renderer/extensions/renderer_extension_bindings.h" 13 #include "chrome/renderer/extensions/renderer_extension_bindings.h"
13 #include "chrome/renderer/js_only_v8_extensions.h" 14 #include "chrome/renderer/js_only_v8_extensions.h"
14 #include "chrome/renderer/render_view.h" 15 #include "chrome/renderer/render_view.h"
15 #include "grit/common_resources.h" 16 #include "grit/common_resources.h"
16 #include "grit/renderer_resources.h" 17 #include "grit/renderer_resources.h"
17 #include "webkit/glue/webframe.h" 18 #include "webkit/glue/webframe.h"
18 19
19 using bindings_utils::GetStringResource; 20 using bindings_utils::GetStringResource;
20 using bindings_utils::ContextInfo; 21 using bindings_utils::ContextInfo;
21 using bindings_utils::ContextList; 22 using bindings_utils::ContextList;
22 using bindings_utils::GetContexts; 23 using bindings_utils::GetContexts;
23 using bindings_utils::GetPendingRequestMap; 24 using bindings_utils::GetPendingRequestMap;
24 using bindings_utils::PendingRequest; 25 using bindings_utils::PendingRequest;
25 using bindings_utils::PendingRequestMap; 26 using bindings_utils::PendingRequestMap;
26 using bindings_utils::ExtensionBase; 27 using bindings_utils::ExtensionBase;
27 28
28 namespace { 29 namespace {
29 30
30 // A map of extension ID to vector of page action ids. 31 // A map of extension ID to vector of page action ids.
31 typedef std::map< std::string, std::vector<std::string> > PageActionIdMap; 32 typedef std::map< std::string, std::vector<std::string> > PageActionIdMap;
32 33
34 // A map of permission name to whether its enabled for this extension.
35 typedef std::map<std::string, bool> PermissionsMap;
36
37 // A map of extension ID to permissions map.
38 typedef std::map<std::string, PermissionsMap> ExtensionPermissionsMap;
39
33 const char kExtensionName[] = "chrome/ExtensionProcessBindings"; 40 const char kExtensionName[] = "chrome/ExtensionProcessBindings";
34 const char* kExtensionDeps[] = { 41 const char* kExtensionDeps[] = {
35 BaseJsV8Extension::kName, 42 BaseJsV8Extension::kName,
36 EventBindings::kName, 43 EventBindings::kName,
37 JsonSchemaJsV8Extension::kName, 44 JsonSchemaJsV8Extension::kName,
38 RendererExtensionBindings::kName, 45 RendererExtensionBindings::kName,
39 }; 46 };
40 47
41 struct SingletonData { 48 struct SingletonData {
42 std::set<std::string> function_names_; 49 std::set<std::string> function_names_;
43 PageActionIdMap page_action_ids_; 50 PageActionIdMap page_action_ids_;
51 ExtensionPermissionsMap permissions_;
44 }; 52 };
45 53
46 static std::set<std::string>* GetFunctionNameSet() { 54 static std::set<std::string>* GetFunctionNameSet() {
47 return &Singleton<SingletonData>()->function_names_; 55 return &Singleton<SingletonData>()->function_names_;
48 } 56 }
49 57
50 static PageActionIdMap* GetPageActionMap() { 58 static PageActionIdMap* GetPageActionMap() {
51 return &Singleton<SingletonData>()->page_action_ids_; 59 return &Singleton<SingletonData>()->page_action_ids_;
52 } 60 }
53 61
62 static PermissionsMap* GetPermissionsMap(const std::string& extension_id) {
63 return &Singleton<SingletonData>()->permissions_[extension_id];
64 }
65
54 class ExtensionImpl : public ExtensionBase { 66 class ExtensionImpl : public ExtensionBase {
55 public: 67 public:
56 ExtensionImpl() : ExtensionBase( 68 ExtensionImpl() : ExtensionBase(
57 kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(), 69 kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(),
58 arraysize(kExtensionDeps), kExtensionDeps) {} 70 arraysize(kExtensionDeps), kExtensionDeps) {}
59 71
60 static void SetFunctionNames(const std::vector<std::string>& names) { 72 static void SetFunctionNames(const std::vector<std::string>& names) {
61 std::set<std::string>* name_set = GetFunctionNameSet(); 73 std::set<std::string>* name_set = GetFunctionNameSet();
62 for (size_t i = 0; i < names.size(); ++i) { 74 for (size_t i = 0; i < names.size(); ++i) {
63 name_set->insert(names[i]); 75 name_set->insert(names[i]);
64 } 76 }
65 } 77 }
66 78
79 // Note: do not call this function before or during the chromeHidden.onLoad
80 // event dispatch. The URL might not have been committed yet and might not
81 // be an extension URL.
82 static std::string ExtensionIdForCurrentContext() {
83 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
84 DCHECK(renderview);
85 GURL url = renderview->webview()->GetMainFrame()->GetURL();
86 if (url.SchemeIs(chrome::kExtensionScheme))
87 return url.host();
88 return std::string();
89 }
90
67 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( 91 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
68 v8::Handle<v8::String> name) { 92 v8::Handle<v8::String> name) {
69 if (name->Equals(v8::String::New("GetExtensionAPIDefinition"))) { 93 if (name->Equals(v8::String::New("GetExtensionAPIDefinition"))) {
70 return v8::FunctionTemplate::New(GetExtensionAPIDefinition); 94 return v8::FunctionTemplate::New(GetExtensionAPIDefinition);
71 } else if (name->Equals(v8::String::New("GetViews"))) { 95 } else if (name->Equals(v8::String::New("GetViews"))) {
72 return v8::FunctionTemplate::New(GetViews); 96 return v8::FunctionTemplate::New(GetViews);
73 } else if (name->Equals(v8::String::New("GetNextRequestId"))) { 97 } else if (name->Equals(v8::String::New("GetNextRequestId"))) {
74 return v8::FunctionTemplate::New(GetNextRequestId); 98 return v8::FunctionTemplate::New(GetNextRequestId);
75 } else if (name->Equals(v8::String::New("OpenChannelToTab"))) { 99 } else if (name->Equals(v8::String::New("OpenChannelToTab"))) {
76 return v8::FunctionTemplate::New(OpenChannelToTab); 100 return v8::FunctionTemplate::New(OpenChannelToTab);
77 } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) { 101 } else if (name->Equals(v8::String::New("GetCurrentPageActions"))) {
78 return v8::FunctionTemplate::New(GetCurrentPageActions); 102 return v8::FunctionTemplate::New(GetCurrentPageActions);
79 } else if (name->Equals(v8::String::New("StartRequest"))) { 103 } else if (name->Equals(v8::String::New("StartRequest"))) {
80 return v8::FunctionTemplate::New(StartRequest); 104 return v8::FunctionTemplate::New(StartRequest);
81 } 105 }
82 106
83 return ExtensionBase::GetNativeFunction(name); 107 return ExtensionBase::GetNativeFunction(name);
84 } 108 }
85 109
86 private: 110 private:
87 static std::string ExtensionIdFromCurrentContext() {
88 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
89 DCHECK(renderview);
90 GURL url = renderview->webview()->GetMainFrame()->GetURL();
91 return url.host();
92 }
93
94 static v8::Handle<v8::Value> GetExtensionAPIDefinition( 111 static v8::Handle<v8::Value> GetExtensionAPIDefinition(
95 const v8::Arguments& args) { 112 const v8::Arguments& args) {
96 return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>()); 113 return v8::String::New(GetStringResource<IDR_EXTENSION_API_JSON>());
97 } 114 }
98 115
99 static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) { 116 static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) {
100 std::string extension_id = ExtensionIdFromCurrentContext(); 117 std::string extension_id = ExtensionIdForCurrentContext();
101 118
102 ContextList contexts = 119 ContextList contexts =
103 bindings_utils::GetContextsForExtension(extension_id); 120 bindings_utils::GetContextsForExtension(extension_id);
104 DCHECK(contexts.size() > 0); 121 DCHECK(contexts.size() > 0);
105 122
106 v8::Local<v8::Array> views = v8::Array::New(contexts.size()); 123 v8::Local<v8::Array> views = v8::Array::New(contexts.size());
107 int index = 0; 124 int index = 0;
108 ContextList::const_iterator it = contexts.begin(); 125 ContextList::const_iterator it = contexts.begin();
109 for (; it != contexts.end(); ++it) { 126 for (; it != contexts.end(); ++it) {
110 v8::Local<v8::Value> window = (*it)->context->Global()->Get( 127 v8::Local<v8::Value> window = (*it)->context->Global()->Get(
(...skipping 27 matching lines...) Expand all
138 renderview->Send(new ViewHostMsg_OpenChannelToTab( 155 renderview->Send(new ViewHostMsg_OpenChannelToTab(
139 renderview->routing_id(), tab_id, extension_id, channel_name, 156 renderview->routing_id(), tab_id, extension_id, channel_name,
140 &port_id)); 157 &port_id));
141 return v8::Integer::New(port_id); 158 return v8::Integer::New(port_id);
142 } 159 }
143 return v8::Undefined(); 160 return v8::Undefined();
144 } 161 }
145 162
146 static v8::Handle<v8::Value> GetCurrentPageActions( 163 static v8::Handle<v8::Value> GetCurrentPageActions(
147 const v8::Arguments& args) { 164 const v8::Arguments& args) {
148 std::string extension_id = ExtensionIdFromCurrentContext(); 165 std::string extension_id = *v8::String::Utf8Value(args[0]->ToString());
149 PageActionIdMap* page_action_map = 166 PageActionIdMap* page_action_map = GetPageActionMap();
150 GetPageActionMap(); 167 PageActionIdMap::const_iterator it = page_action_map->find(extension_id);
151 PageActionIdMap::const_iterator it =
152 page_action_map->find(extension_id);
153 168
154 std::vector<std::string> page_actions; 169 std::vector<std::string> page_actions;
155 size_t size = 0; 170 size_t size = 0;
156 if (it != page_action_map->end()) { 171 if (it != page_action_map->end()) {
157 page_actions = it->second; 172 page_actions = it->second;
158 size = page_actions.size(); 173 size = page_actions.size();
159 } 174 }
160 175
161 v8::Local<v8::Array> page_action_vector = v8::Array::New(size); 176 v8::Local<v8::Array> page_action_vector = v8::Array::New(size);
162 for (size_t i = 0; i < size; ++i) { 177 for (size_t i = 0; i < size; ++i) {
(...skipping 17 matching lines...) Expand all
180 if (args.Length() != 4 || !args[0]->IsString() || !args[1]->IsString() || 195 if (args.Length() != 4 || !args[0]->IsString() || !args[1]->IsString() ||
181 !args[2]->IsInt32() || !args[3]->IsBoolean()) 196 !args[2]->IsInt32() || !args[3]->IsBoolean())
182 return v8::Undefined(); 197 return v8::Undefined();
183 198
184 std::string name = *v8::String::AsciiValue(args[0]); 199 std::string name = *v8::String::AsciiValue(args[0]);
185 if (GetFunctionNameSet()->find(name) == GetFunctionNameSet()->end()) { 200 if (GetFunctionNameSet()->find(name) == GetFunctionNameSet()->end()) {
186 NOTREACHED() << "Unexpected function " << name; 201 NOTREACHED() << "Unexpected function " << name;
187 return v8::Undefined(); 202 return v8::Undefined();
188 } 203 }
189 204
205 if (!ExtensionProcessBindings::CurrentContextHasPermission(name))
206 return ExtensionProcessBindings::ThrowPermissionDeniedException(name);
207
190 std::string json_args = *v8::String::Utf8Value(args[1]); 208 std::string json_args = *v8::String::Utf8Value(args[1]);
191 int request_id = args[2]->Int32Value(); 209 int request_id = args[2]->Int32Value();
192 bool has_callback = args[3]->BooleanValue(); 210 bool has_callback = args[3]->BooleanValue();
193 211
194 v8::Persistent<v8::Context> current_context = 212 v8::Persistent<v8::Context> current_context =
195 v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); 213 v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
196 DCHECK(!current_context.IsEmpty()); 214 DCHECK(!current_context.IsEmpty());
197 GetPendingRequestMap()[request_id].reset(new PendingRequest( 215 GetPendingRequestMap()[request_id].reset(new PendingRequest(
198 current_context, *v8::String::AsciiValue(args.Data()))); 216 current_context, *v8::String::AsciiValue(args.Data())));
199 217
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 const std::string& extension_id, 260 const std::string& extension_id,
243 const std::vector<std::string>& page_actions) { 261 const std::vector<std::string>& page_actions) {
244 PageActionIdMap& page_action_map = *GetPageActionMap(); 262 PageActionIdMap& page_action_map = *GetPageActionMap();
245 if (!page_actions.empty()) { 263 if (!page_actions.empty()) {
246 page_action_map[extension_id] = page_actions; 264 page_action_map[extension_id] = page_actions;
247 } else { 265 } else {
248 if (page_action_map.find(extension_id) != page_action_map.end()) 266 if (page_action_map.find(extension_id) != page_action_map.end())
249 page_action_map.erase(extension_id); 267 page_action_map.erase(extension_id);
250 } 268 }
251 } 269 }
270
271 // static
272 void ExtensionProcessBindings::SetPermissions(
273 const std::string& extension_id,
274 const std::vector<std::string>& permissions) {
275 PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
276
277 // Default all permissions to false, then enable the ones in the vector.
278 for (size_t i = 0; i < Extension::kNumPermissions; ++i)
279 permissions_map[Extension::kPermissionNames[i]] = false;
280 for (size_t i = 0; i < permissions.size(); ++i)
281 permissions_map[permissions[i]] = true;
282 }
283
284 // Given a name like "tabs.onConnect", return the permission name required
285 // to access that API ("tabs" in this example).
286 static std::string GetPermissionName(const std::string& function_name) {
287 size_t first_dot = function_name.find('.');
288 std::string permission_name = function_name.substr(0, first_dot);
289 if (permission_name == "windows")
290 return "tabs"; // windows and tabs are the same permission.
291 return permission_name;
292 }
293
294 // static
295 bool ExtensionProcessBindings::CurrentContextHasPermission(
296 const std::string& function_name) {
297 std::string extension_id = ExtensionImpl::ExtensionIdForCurrentContext();
298 PermissionsMap& permissions_map = *GetPermissionsMap(extension_id);
299 std::string permission_name = GetPermissionName(function_name);
300 PermissionsMap::iterator it = permissions_map.find(permission_name);
301
302 // We explicitly check if the permission entry is present and false, because
303 // some APIs do not have a required permission entry (ie, "chrome.self").
304 return (it == permissions_map.end() || it->second);
305 }
306
307 // static
308 v8::Handle<v8::Value>
309 ExtensionProcessBindings::ThrowPermissionDeniedException(
310 const std::string& function_name) {
311 static const char kMessage[] =
312 "You do not have permission to use 'chrome.%s'. Be sure to declare"
313 " in your manifest what permissions you need.";
314 std::string permission_name = GetPermissionName(function_name);
315 std::string error_msg = StringPrintf(kMessage, permission_name.c_str());
316
317 #if EXTENSION_TIME_TO_BREAK_API
318 return v8::ThrowException(v8::Exception::Error(
319 v8::String::New(error_msg.c_str())));
320 #else
321 // Call console.error for now.
322
323 v8::HandleScope scope;
324
325 v8::Local<v8::Value> console =
326 v8::Context::GetCurrent()->Global()->Get(v8::String::New("console"));
327 v8::Local<v8::Value> console_error;
328 if (!console.IsEmpty() && console->IsObject())
329 console_error = console->ToObject()->Get(v8::String::New("error"));
330 if (console_error.IsEmpty() || !console_error->IsFunction())
331 return v8::Undefined();
332
333 v8::Local<v8::Function> function =
334 v8::Local<v8::Function>::Cast(console_error);
335 v8::Local<v8::Value> argv[] = { v8::String::New(error_msg.c_str()) };
336 if (!function.IsEmpty())
337 function->Call(console->ToObject(), arraysize(argv), argv);
338
339 return v8::Undefined();
340 #endif
341 }
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/extension_process_bindings.h ('k') | chrome/renderer/render_thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698