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

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

Issue 147033: Refactor extension bindings to share code, avoid exposing hidden variables (Closed)
Patch Set: at head Created 11 years, 5 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 "base/stl_util-inl.h"
9 #include "chrome/common/render_messages.h" 8 #include "chrome/common/render_messages.h"
10 #include "chrome/common/url_constants.h" 9 #include "chrome/common/url_constants.h"
11 #include "chrome/renderer/extensions/bindings_utils.h" 10 #include "chrome/renderer/extensions/bindings_utils.h"
12 #include "chrome/renderer/extensions/event_bindings.h" 11 #include "chrome/renderer/extensions/event_bindings.h"
13 #include "chrome/renderer/extensions/renderer_extension_bindings.h" 12 #include "chrome/renderer/extensions/renderer_extension_bindings.h"
14 #include "chrome/renderer/js_only_v8_extensions.h" 13 #include "chrome/renderer/js_only_v8_extensions.h"
15 #include "chrome/renderer/render_view.h" 14 #include "chrome/renderer/render_view.h"
16 #include "grit/renderer_resources.h" 15 #include "grit/renderer_resources.h"
17 #include "webkit/api/public/WebScriptSource.h"
18 #include "webkit/glue/webframe.h" 16 #include "webkit/glue/webframe.h"
19 17
20 using WebKit::WebScriptSource; 18 using bindings_utils::GetStringResource;
21 using WebKit::WebString; 19 using bindings_utils::ContextInfo;
20 using bindings_utils::ContextList;
21 using bindings_utils::GetContexts;
22 using bindings_utils::ExtensionBase;
22 23
23 namespace { 24 namespace {
24 25
25 const char kExtensionName[] = "chrome/ExtensionProcessBindings"; 26 const char kExtensionName[] = "chrome/ExtensionProcessBindings";
26 const char* kExtensionDeps[] = { 27 const char* kExtensionDeps[] = {
27 BaseJsV8Extension::kName, 28 BaseJsV8Extension::kName,
28 EventBindings::kName, 29 EventBindings::kName,
29 JsonSchemaJsV8Extension::kName, 30 JsonSchemaJsV8Extension::kName,
30 RendererExtensionBindings::kName, 31 RendererExtensionBindings::kName,
31 }; 32 };
32 33
33 // Types for storage of per-renderer-singleton data structure that maps
34 // |extension_id| -> <List of v8 Contexts for the "views" of that extension>
35 typedef std::list< v8::Persistent<v8::Context> > ContextList;
36 typedef std::map<std::string, ContextList> ExtensionIdContextsMap;
37
38 // Contains info relevant to a pending request.
39 struct CallContext {
40 public :
41 CallContext(v8::Persistent<v8::Context> context, const std::string& name)
42 : context(context), name(name) {
43 }
44 v8::Persistent<v8::Context> context;
45 std::string name;
46 };
47 typedef std::map<int, CallContext*> PendingRequestMap;
48
49 struct SingletonData { 34 struct SingletonData {
50 std::set<std::string> function_names_; 35 std::set<std::string> function_names_;
51 ExtensionIdContextsMap contexts;
52 PendingRequestMap pending_requests;
53
54 ~SingletonData() {
55 STLDeleteContainerPairSecondPointers(pending_requests.begin(),
56 pending_requests.end());
57 }
58 }; 36 };
59 37
60 static std::set<std::string>* GetFunctionNameSet() { 38 static std::set<std::string>* GetFunctionNameSet() {
61 return &Singleton<SingletonData>()->function_names_; 39 return &Singleton<SingletonData>()->function_names_;
62 } 40 }
63 41
64 static ContextList& GetRegisteredContexts(std::string extension_id) { 42 class ExtensionImpl : public ExtensionBase {
65 return Singleton<SingletonData>::get()->contexts[extension_id];
66 }
67
68 static PendingRequestMap& GetPendingRequestMap() {
69 return Singleton<SingletonData>::get()->pending_requests;
70 }
71
72 class ExtensionImpl : public v8::Extension {
73 public: 43 public:
74 ExtensionImpl() : v8::Extension( 44 ExtensionImpl() : ExtensionBase(
75 kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(), 45 kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(),
76 arraysize(kExtensionDeps), kExtensionDeps) {} 46 arraysize(kExtensionDeps), kExtensionDeps) {}
77 47
78 static void SetFunctionNames(const std::vector<std::string>& names) { 48 static void SetFunctionNames(const std::vector<std::string>& names) {
79 std::set<std::string>* name_set = GetFunctionNameSet(); 49 std::set<std::string>* name_set = GetFunctionNameSet();
80 for (size_t i = 0; i < names.size(); ++i) { 50 for (size_t i = 0; i < names.size(); ++i) {
81 name_set->insert(names[i]); 51 name_set->insert(names[i]);
82 } 52 }
83 } 53 }
84 54
85 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( 55 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
86 v8::Handle<v8::String> name) { 56 v8::Handle<v8::String> name) {
87 std::set<std::string>* names = GetFunctionNameSet(); 57 std::set<std::string>* names = GetFunctionNameSet();
88 58
89 if (name->Equals(v8::String::New("GetNextRequestId"))) 59 if (name->Equals(v8::String::New("GetViews"))) {
90 return v8::FunctionTemplate::New(GetNextRequestId);
91 else if (name->Equals(v8::String::New("RegisterExtension")))
92 return v8::FunctionTemplate::New(RegisterExtension);
93 else if (name->Equals(v8::String::New("UnregisterExtension")))
94 return v8::FunctionTemplate::New(UnregisterExtension);
95 else if (name->Equals(v8::String::New("GetViews")))
96 return v8::FunctionTemplate::New(GetViews); 60 return v8::FunctionTemplate::New(GetViews);
97 else if (names->find(*v8::String::AsciiValue(name)) != names->end()) 61 } else if (names->find(*v8::String::AsciiValue(name)) != names->end()) {
98 return v8::FunctionTemplate::New(StartRequest, name); 62 return v8::FunctionTemplate::New(ExtensionBase::StartRequest, name);
63 }
99 64
100 return v8::Handle<v8::FunctionTemplate>(); 65 return ExtensionBase::GetNativeFunction(name);
101 } 66 }
102 67
103 private: 68 private:
104 static v8::Handle<v8::Value> RegisterExtension(const v8::Arguments& args) {
105 RenderView* renderview = GetRenderViewForCurrentContext();
106 DCHECK(renderview);
107 GURL url = renderview->webview()->GetMainFrame()->GetURL();
108 DCHECK(url.scheme() == chrome::kExtensionScheme);
109
110 v8::Persistent<v8::Context> current_context =
111 v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
112 DCHECK(!current_context.IsEmpty());
113
114 std::string extension_id = url.host();
115 GetRegisteredContexts(extension_id).push_back(current_context);
116 return v8::String::New(extension_id.c_str());
117 }
118
119 static v8::Handle<v8::Value> UnregisterExtension(const v8::Arguments& args) {
120 DCHECK_EQ(args.Length(), 1);
121 DCHECK(args[0]->IsString());
122
123 v8::Local<v8::Context> current_context = v8::Context::GetCurrent();
124 DCHECK(!current_context.IsEmpty());
125
126 // Remove all pending requests for this context.
127 PendingRequestMap& pending_requests = GetPendingRequestMap();
128 for (PendingRequestMap::iterator it = pending_requests.begin();
129 it != pending_requests.end(); ) {
130 PendingRequestMap::iterator current = it++;
131 if (current->second->context == current_context) {
132 current->second->context.Dispose();
133 current->second->context.Clear();
134 delete current->second;
135 pending_requests.erase(current);
136 }
137 }
138
139 std::string extension_id(*v8::String::Utf8Value(args[0]));
140 ContextList& contexts = GetRegisteredContexts(extension_id);
141 ContextList::iterator it = std::find(contexts.begin(), contexts.end(),
142 current_context);
143 if (it == contexts.end()) {
144 NOTREACHED();
145 return v8::Undefined();
146 }
147
148 it->Dispose();
149 it->Clear();
150 contexts.erase(it);
151
152 return v8::Undefined();
153 }
154
155 static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) { 69 static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) {
156 RenderView* renderview = GetRenderViewForCurrentContext(); 70 RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
157 DCHECK(renderview); 71 DCHECK(renderview);
158 GURL url = renderview->webview()->GetMainFrame()->GetURL(); 72 GURL url = renderview->webview()->GetMainFrame()->GetURL();
159 std::string extension_id = url.host(); 73 std::string extension_id = url.host();
160 74
161 ContextList& contexts = GetRegisteredContexts(extension_id); 75 ContextList contexts =
76 bindings_utils::GetContextsForExtension(extension_id);
162 DCHECK(contexts.size() > 0); 77 DCHECK(contexts.size() > 0);
163 78
164 v8::Local<v8::Array> views = v8::Array::New(contexts.size()); 79 v8::Local<v8::Array> views = v8::Array::New(contexts.size());
165 int index = 0; 80 int index = 0;
166 ContextList::const_iterator it = contexts.begin(); 81 ContextList::const_iterator it = contexts.begin();
167 for (; it != contexts.end(); ++it) { 82 for (; it != contexts.end(); ++it) {
168 v8::Local<v8::Value> window = (*it)->Global()->Get( 83 v8::Local<v8::Value> window = (*it)->context->Global()->Get(
169 v8::String::New("window")); 84 v8::String::New("window"));
170 DCHECK(!window.IsEmpty()); 85 DCHECK(!window.IsEmpty());
171 views->Set(v8::Integer::New(index), window); 86 views->Set(v8::Integer::New(index), window);
172 index++; 87 index++;
173 } 88 }
174 return views; 89 return views;
175 } 90 }
176
177 static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) {
178 static int next_request_id = 0;
179 return v8::Integer::New(next_request_id++);
180 }
181
182 static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) {
183 // Get the current RenderView so that we can send a routed IPC message from
184 // the correct source.
185 RenderView* renderview = GetRenderViewForCurrentContext();
186 if (!renderview)
187 return v8::Undefined();
188
189 if (args.Length() != 3 || !args[0]->IsString() || !args[1]->IsInt32() ||
190 !args[2]->IsBoolean())
191 return v8::Undefined();
192
193 std::string name = *v8::String::AsciiValue(args.Data());
194 std::string json_args = *v8::String::Utf8Value(args[0]);
195 int request_id = args[1]->Int32Value();
196 bool has_callback = args[2]->BooleanValue();
197
198 v8::Persistent<v8::Context> current_context =
199 v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
200 DCHECK(!current_context.IsEmpty());
201 GetPendingRequestMap()[request_id] =
202 new CallContext(current_context, *v8::String::AsciiValue(args.Data()));
203
204 renderview->SendExtensionRequest(name, json_args, request_id, has_callback);
205
206 return v8::Undefined();
207 }
208 }; 91 };
209 92
210 } // namespace 93 } // namespace
211 94
212 v8::Extension* ExtensionProcessBindings::Get() { 95 v8::Extension* ExtensionProcessBindings::Get() {
213 return new ExtensionImpl(); 96 return new ExtensionImpl();
214 } 97 }
215 98
216 void ExtensionProcessBindings::SetFunctionNames( 99 void ExtensionProcessBindings::SetFunctionNames(
217 const std::vector<std::string>& names) { 100 const std::vector<std::string>& names) {
218 ExtensionImpl::SetFunctionNames(names); 101 ExtensionImpl::SetFunctionNames(names);
219 } 102 }
220
221 void ExtensionProcessBindings::RegisterExtensionContext(WebFrame* frame) {
222 frame->ExecuteScript(WebScriptSource(WebString::fromUTF8(
223 "chrome.self.register_();")));
224 }
225
226 void ExtensionProcessBindings::HandleResponse(int request_id, bool success,
227 const std::string& response,
228 const std::string& error) {
229 CallContext* call = GetPendingRequestMap()[request_id];
230 if (!call)
231 return; // The frame went away.
232
233 v8::HandleScope handle_scope;
234 v8::Handle<v8::Value> argv[5];
235 argv[0] = v8::Integer::New(request_id);
236 argv[1] = v8::String::New(call->name.c_str());
237 argv[2] = v8::Boolean::New(success);
238 argv[3] = v8::String::New(response.c_str());
239 argv[4] = v8::String::New(error.c_str());
240 CallFunctionInContext(call->context, "chrome.handleResponse_",
241 arraysize(argv), argv);
242
243 GetPendingRequestMap().erase(request_id);
244 delete call;
245 }
OLDNEW
« no previous file with comments | « chrome/renderer/extensions/extension_process_bindings.h ('k') | chrome/renderer/extensions/renderer_extension_bindings.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698