| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/bindings_utils.h" | 5 #include "chrome/renderer/extensions/bindings_utils.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | |
| 8 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
| 9 #include "base/stringprintf.h" | |
| 10 #include "base/string_split.h" | 8 #include "base/string_split.h" |
| 11 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 12 #include "chrome/common/extensions/extension.h" | |
| 13 #include "chrome/common/extensions/extension_set.h" | |
| 14 #include "chrome/renderer/extensions/extension_dispatcher.h" | |
| 15 #include "content/renderer/render_view.h" | 10 #include "content/renderer/render_view.h" |
| 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 19 #include "v8/include/v8.h" | 13 #include "v8/include/v8.h" |
| 20 | 14 |
| 21 using WebKit::WebFrame; | 15 using WebKit::WebFrame; |
| 22 using WebKit::WebView; | 16 using WebKit::WebView; |
| 23 | 17 |
| 24 namespace bindings_utils { | 18 namespace bindings_utils { |
| 25 | 19 |
| 26 const char* kChromeHidden = "chromeHidden"; | 20 const char* kChromeHidden = "chromeHidden"; |
| 27 const char* kValidateCallbacks = "validateCallbacks"; | 21 const char* kValidateCallbacks = "validateCallbacks"; |
| 28 | 22 |
| 29 struct SingletonData { | 23 struct SingletonData { |
| 30 ContextList contexts; | 24 ContextList contexts; |
| 31 PendingRequestMap pending_requests; | 25 PendingRequestMap pending_requests; |
| 32 }; | 26 }; |
| 33 static base::LazyInstance<SingletonData> g_singleton_data( | 27 static base::LazyInstance<SingletonData> g_singleton_data( |
| 34 base::LINKER_INITIALIZED); | 28 base::LINKER_INITIALIZED); |
| 35 | 29 |
| 36 typedef std::map<int, std::string> StringMap; | |
| 37 static base::LazyInstance<StringMap> g_string_map(base::LINKER_INITIALIZED); | |
| 38 | |
| 39 const char* GetStringResource(int resource_id) { | |
| 40 StringMap* strings = g_string_map.Pointer(); | |
| 41 StringMap::iterator it = strings->find(resource_id); | |
| 42 if (it == strings->end()) { | |
| 43 it = strings->insert(std::make_pair( | |
| 44 resource_id, | |
| 45 ResourceBundle::GetSharedInstance().GetRawDataResource( | |
| 46 resource_id).as_string())).first; | |
| 47 } | |
| 48 return it->second.c_str(); | |
| 49 } | |
| 50 | |
| 51 // ExtensionBase | |
| 52 | |
| 53 const Extension* ExtensionBase::GetExtensionForCurrentContext() const { | |
| 54 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext(); | |
| 55 if (!renderview) | |
| 56 return NULL; // this can happen as a tab is closing. | |
| 57 | |
| 58 GURL url = renderview->webview()->mainFrame()->document().url(); | |
| 59 const ExtensionSet* extensions = extension_dispatcher_->extensions(); | |
| 60 if (!extensions->ExtensionBindingsAllowed(url)) | |
| 61 return NULL; | |
| 62 | |
| 63 return extensions->GetByURL(url); | |
| 64 } | |
| 65 | |
| 66 bool ExtensionBase::CheckPermissionForCurrentContext( | |
| 67 const std::string& function_name) const { | |
| 68 const ::Extension* extension = GetExtensionForCurrentContext(); | |
| 69 if (extension && | |
| 70 extension_dispatcher_->IsExtensionActive(extension->id()) && | |
| 71 extension->HasAPIPermission(function_name)) | |
| 72 return true; | |
| 73 | |
| 74 static const char kMessage[] = | |
| 75 "You do not have permission to use '%s'. Be sure to declare" | |
| 76 " in your manifest what permissions you need."; | |
| 77 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); | |
| 78 | |
| 79 v8::ThrowException(v8::Exception::Error(v8::String::New(error_msg.c_str()))); | |
| 80 return false; | |
| 81 } | |
| 82 | |
| 83 v8::Handle<v8::FunctionTemplate> | |
| 84 ExtensionBase::GetNativeFunction(v8::Handle<v8::String> name) { | |
| 85 if (name->Equals(v8::String::New("GetChromeHidden"))) { | |
| 86 return v8::FunctionTemplate::New(GetChromeHidden); | |
| 87 } | |
| 88 | |
| 89 if (name->Equals(v8::String::New("Print"))) { | |
| 90 return v8::FunctionTemplate::New(Print); | |
| 91 } | |
| 92 | |
| 93 return v8::Handle<v8::FunctionTemplate>(); | |
| 94 } | |
| 95 | |
| 96 v8::Handle<v8::Value> ExtensionBase::GetChromeHidden( | |
| 97 const v8::Arguments& args) { | |
| 98 v8::Local<v8::Context> context = v8::Context::GetCurrent(); | |
| 99 v8::Local<v8::Object> global = context->Global(); | |
| 100 v8::Local<v8::Value> hidden = global->GetHiddenValue( | |
| 101 v8::String::New(kChromeHidden)); | |
| 102 | |
| 103 if (hidden.IsEmpty() || hidden->IsUndefined()) { | |
| 104 hidden = v8::Object::New(); | |
| 105 global->SetHiddenValue(v8::String::New(kChromeHidden), hidden); | |
| 106 | |
| 107 #ifndef NDEBUG | |
| 108 // Tell extension_process_bindings.js to validate callbacks and events | |
| 109 // against their schema definitions in api/extension_api.json. | |
| 110 v8::Local<v8::Object>::Cast(hidden) | |
| 111 ->Set(v8::String::New(kValidateCallbacks), v8::True()); | |
| 112 #endif | |
| 113 } | |
| 114 | |
| 115 DCHECK(hidden->IsObject()); | |
| 116 return hidden; | |
| 117 } | |
| 118 | |
| 119 v8::Handle<v8::Value> ExtensionBase::Print(const v8::Arguments& args) { | |
| 120 if (args.Length() < 1) | |
| 121 return v8::Undefined(); | |
| 122 | |
| 123 std::vector<std::string> components; | |
| 124 for (int i = 0; i < args.Length(); ++i) | |
| 125 components.push_back(*v8::String::Utf8Value(args[i]->ToString())); | |
| 126 | |
| 127 LOG(ERROR) << JoinString(components, ','); | |
| 128 return v8::Undefined(); | |
| 129 } | |
| 130 | |
| 131 ContextInfo::ContextInfo(v8::Persistent<v8::Context> context, | 30 ContextInfo::ContextInfo(v8::Persistent<v8::Context> context, |
| 132 const std::string& extension_id, | 31 const std::string& extension_id, |
| 133 WebFrame* frame) | 32 WebFrame* frame) |
| 134 : context(context), | 33 : context(context), |
| 135 extension_id(extension_id), | 34 extension_id(extension_id), |
| 136 unsafe_frame(frame), | 35 unsafe_frame(frame), |
| 137 num_connected_events(0) { | 36 num_connected_events(0) { |
| 138 } | 37 } |
| 139 | 38 |
| 140 ContextInfo::~ContextInfo() {} | 39 ContextInfo::~ContextInfo() {} |
| 141 | 40 |
| 142 ContextList& GetContexts() { | 41 ContextList& GetContexts() { |
| 143 return g_singleton_data.Get().contexts; | 42 return g_singleton_data.Get().contexts; |
| 144 } | 43 } |
| 145 | 44 |
| 146 ContextInfo* GetInfoForCurrentContext() { | 45 ContextInfo* GetInfoForCurrentContext() { |
| 147 // This can happen in testing scenarios and v8::Context::GetCurrent() crashes | 46 // This can happen in testing scenarios and v8::Context::GetCurrent() crashes |
| 148 // if there is no JavaScript currently running. | 47 // if there is no JavaScript currently running. |
| 149 if (!v8::Context::InContext()) | 48 if (!v8::Context::InContext()) |
| 150 return NULL; | 49 return NULL; |
| 151 | 50 |
| 152 v8::Local<v8::Context> context = v8::Context::GetCurrent(); | 51 v8::Local<v8::Context> context = v8::Context::GetCurrent(); |
| 153 ContextList::iterator context_iter = FindContext(context); | 52 ContextList::iterator context_iter = FindContext(context); |
| 154 if (context_iter == GetContexts().end()) | 53 if (context_iter == GetContexts().end()) |
| 155 return NULL; | 54 return NULL; |
| 156 else | 55 else |
| 157 return context_iter->get(); | 56 return context_iter->get(); |
| 158 } | 57 } |
| 159 | 58 |
| 59 v8::Handle<v8::Object> GetChromeHiddenForContext( |
| 60 v8::Handle<v8::Context> context) { |
| 61 v8::Local<v8::Object> global = context->Global(); |
| 62 v8::Local<v8::Value> hidden = global->GetHiddenValue( |
| 63 v8::String::New(kChromeHidden)); |
| 64 |
| 65 if (hidden.IsEmpty() || hidden->IsUndefined()) { |
| 66 hidden = v8::Object::New(); |
| 67 global->SetHiddenValue(v8::String::New(kChromeHidden), hidden); |
| 68 |
| 69 #ifndef NDEBUG |
| 70 // Tell extension_process_bindings.js to validate callbacks and events |
| 71 // against their schema definitions in api/extension_api.json. |
| 72 v8::Local<v8::Object>::Cast(hidden) |
| 73 ->Set(v8::String::New(kValidateCallbacks), v8::True()); |
| 74 #endif |
| 75 } |
| 76 |
| 77 DCHECK(hidden->IsObject()); |
| 78 return v8::Local<v8::Object>::Cast(hidden); |
| 79 } |
| 80 |
| 160 PendingRequest::PendingRequest(v8::Persistent<v8::Context> context, | 81 PendingRequest::PendingRequest(v8::Persistent<v8::Context> context, |
| 161 const std::string& name) | 82 const std::string& name) |
| 162 : context(context), name(name) { | 83 : context(context), name(name) { |
| 163 } | 84 } |
| 164 | 85 |
| 165 PendingRequest::~PendingRequest() {} | 86 PendingRequest::~PendingRequest() {} |
| 166 | 87 |
| 167 ContextList::iterator FindContext(v8::Handle<v8::Context> context) { | 88 ContextList::iterator FindContext(v8::Handle<v8::Context> context) { |
| 168 ContextList& all_contexts = GetContexts(); | 89 ContextList& all_contexts = GetContexts(); |
| 169 | 90 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 } | 137 } |
| 217 | 138 |
| 218 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value); | 139 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value); |
| 219 if (!function.IsEmpty()) | 140 if (!function.IsEmpty()) |
| 220 return function->Call(v8::Object::New(), argc, argv); | 141 return function->Call(v8::Object::New(), argc, argv); |
| 221 | 142 |
| 222 return v8::Undefined(); | 143 return v8::Undefined(); |
| 223 } | 144 } |
| 224 | 145 |
| 225 } // namespace bindings_utils | 146 } // namespace bindings_utils |
| OLD | NEW |