| OLD | NEW |
| 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/render_messages.h" | 8 #include "chrome/common/render_messages.h" |
| 9 #include "chrome/common/url_constants.h" |
| 9 #include "chrome/renderer/extensions/bindings_utils.h" | 10 #include "chrome/renderer/extensions/bindings_utils.h" |
| 10 #include "chrome/renderer/extensions/event_bindings.h" | 11 #include "chrome/renderer/extensions/event_bindings.h" |
| 11 #include "chrome/renderer/extensions/renderer_extension_bindings.h" | 12 #include "chrome/renderer/extensions/renderer_extension_bindings.h" |
| 12 #include "chrome/renderer/js_only_v8_extensions.h" | 13 #include "chrome/renderer/js_only_v8_extensions.h" |
| 13 #include "chrome/renderer/render_view.h" | 14 #include "chrome/renderer/render_view.h" |
| 14 #include "grit/renderer_resources.h" | 15 #include "grit/renderer_resources.h" |
| 15 #include "webkit/api/public/WebScriptSource.h" | 16 #include "webkit/api/public/WebScriptSource.h" |
| 16 #include "webkit/glue/webframe.h" | 17 #include "webkit/glue/webframe.h" |
| 17 | 18 |
| 18 using WebKit::WebScriptSource; | 19 using WebKit::WebScriptSource; |
| 19 using WebKit::WebString; | 20 using WebKit::WebString; |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 const char kExtensionName[] = "chrome/ExtensionProcessBindings"; | 24 const char kExtensionName[] = "chrome/ExtensionProcessBindings"; |
| 24 const char* kExtensionDeps[] = { | 25 const char* kExtensionDeps[] = { |
| 25 BaseJsV8Extension::kName, | 26 BaseJsV8Extension::kName, |
| 26 EventBindings::kName, | 27 EventBindings::kName, |
| 27 JsonJsV8Extension::kName, | 28 JsonJsV8Extension::kName, |
| 28 JsonSchemaJsV8Extension::kName, | 29 JsonSchemaJsV8Extension::kName, |
| 29 RendererExtensionBindings::kName, | 30 RendererExtensionBindings::kName, |
| 30 }; | 31 }; |
| 31 | 32 |
| 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 struct ExtensionViewContexts { |
| 38 ExtensionIdContextsMap contexts; |
| 39 }; |
| 40 |
| 32 class ExtensionImpl : public v8::Extension { | 41 class ExtensionImpl : public v8::Extension { |
| 33 public: | 42 public: |
| 34 ExtensionImpl() : v8::Extension( | 43 ExtensionImpl() : v8::Extension( |
| 35 kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(), | 44 kExtensionName, GetStringResource<IDR_EXTENSION_PROCESS_BINDINGS_JS>(), |
| 36 arraysize(kExtensionDeps), kExtensionDeps) {} | 45 arraysize(kExtensionDeps), kExtensionDeps) {} |
| 37 | 46 |
| 38 static void SetFunctionNames(const std::vector<std::string>& names) { | 47 static void SetFunctionNames(const std::vector<std::string>& names) { |
| 39 std::set<std::string>* name_set = GetFunctionNameSet(); | 48 std::set<std::string>* name_set = GetFunctionNameSet(); |
| 40 for (size_t i = 0; i < names.size(); ++i) { | 49 for (size_t i = 0; i < names.size(); ++i) { |
| 41 name_set->insert(names[i]); | 50 name_set->insert(names[i]); |
| 42 } | 51 } |
| 43 } | 52 } |
| 44 | 53 |
| 45 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 54 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
| 46 v8::Handle<v8::String> name) { | 55 v8::Handle<v8::String> name) { |
| 47 std::set<std::string>* names = GetFunctionNameSet(); | 56 std::set<std::string>* names = GetFunctionNameSet(); |
| 48 | 57 |
| 49 if (name->Equals(v8::String::New("GetNextRequestId"))) | 58 if (name->Equals(v8::String::New("GetNextRequestId"))) |
| 50 return v8::FunctionTemplate::New(GetNextRequestId); | 59 return v8::FunctionTemplate::New(GetNextRequestId); |
| 60 else if (name->Equals(v8::String::New("RegisterExtension"))) |
| 61 return v8::FunctionTemplate::New(RegisterExtension); |
| 62 else if (name->Equals(v8::String::New("UnregisterExtension"))) |
| 63 return v8::FunctionTemplate::New(UnregisterExtension); |
| 64 else if (name->Equals(v8::String::New("GetViews"))) |
| 65 return v8::FunctionTemplate::New(GetViews); |
| 51 else if (names->find(*v8::String::AsciiValue(name)) != names->end()) | 66 else if (names->find(*v8::String::AsciiValue(name)) != names->end()) |
| 52 return v8::FunctionTemplate::New(StartRequest, name); | 67 return v8::FunctionTemplate::New(StartRequest, name); |
| 53 | 68 |
| 54 return v8::Handle<v8::FunctionTemplate>(); | 69 return v8::Handle<v8::FunctionTemplate>(); |
| 55 } | 70 } |
| 56 | 71 |
| 57 private: | 72 private: |
| 58 struct SingletonData { | 73 struct SingletonData { |
| 59 std::set<std::string> function_names_; | 74 std::set<std::string> function_names_; |
| 60 }; | 75 }; |
| 61 | 76 |
| 62 static std::set<std::string>* GetFunctionNameSet() { | 77 static std::set<std::string>* GetFunctionNameSet() { |
| 63 return &Singleton<SingletonData>()->function_names_; | 78 return &Singleton<SingletonData>()->function_names_; |
| 64 } | 79 } |
| 65 | 80 |
| 81 static ContextList& GetRegisteredContexts(std::string extension_id) { |
| 82 return Singleton<ExtensionViewContexts>::get()->contexts[extension_id]; |
| 83 } |
| 84 |
| 85 static v8::Handle<v8::Value> RegisterExtension(const v8::Arguments& args) { |
| 86 RenderView* renderview = GetRenderViewForCurrentContext(); |
| 87 DCHECK(renderview); |
| 88 GURL url = renderview->webview()->GetMainFrame()->GetURL(); |
| 89 DCHECK(url.scheme() == chrome::kExtensionScheme); |
| 90 |
| 91 v8::Persistent<v8::Context> current_context = |
| 92 v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); |
| 93 DCHECK(!current_context.IsEmpty()); |
| 94 |
| 95 std::string extension_id = url.host(); |
| 96 GetRegisteredContexts(extension_id).push_back(current_context); |
| 97 return v8::String::New(extension_id.c_str()); |
| 98 } |
| 99 |
| 100 static v8::Handle<v8::Value> UnregisterExtension(const v8::Arguments& args) { |
| 101 DCHECK_EQ(args.Length(), 1); |
| 102 DCHECK(args[0]->IsString()); |
| 103 |
| 104 std::string extension_id(*v8::String::Utf8Value(args[0])); |
| 105 ContextList& contexts = GetRegisteredContexts(extension_id); |
| 106 v8::Local<v8::Context> current_context = v8::Context::GetCurrent(); |
| 107 DCHECK(!current_context.IsEmpty()); |
| 108 |
| 109 ContextList::iterator it = std::find(contexts.begin(), contexts.end(), |
| 110 current_context); |
| 111 if (it == contexts.end()) { |
| 112 NOTREACHED(); |
| 113 return v8::Undefined(); |
| 114 } |
| 115 |
| 116 it->Dispose(); |
| 117 it->Clear(); |
| 118 contexts.erase(it); |
| 119 |
| 120 return v8::Undefined(); |
| 121 } |
| 122 |
| 123 static v8::Handle<v8::Value> GetViews(const v8::Arguments& args) { |
| 124 RenderView* renderview = GetRenderViewForCurrentContext(); |
| 125 DCHECK(renderview); |
| 126 GURL url = renderview->webview()->GetMainFrame()->GetURL(); |
| 127 std::string extension_id = url.host(); |
| 128 |
| 129 ContextList& contexts = GetRegisteredContexts(extension_id); |
| 130 DCHECK(contexts.size() > 0); |
| 131 |
| 132 v8::Local<v8::Array> views = v8::Array::New(contexts.size()); |
| 133 int index = 0; |
| 134 ContextList::const_iterator it = contexts.begin(); |
| 135 for (; it != contexts.end(); ++it) { |
| 136 v8::Local<v8::Value> window = (*it)->Global()->Get( |
| 137 v8::String::New("window")); |
| 138 DCHECK(!window.IsEmpty()); |
| 139 views->Set(v8::Integer::New(index), window); |
| 140 index++; |
| 141 } |
| 142 return views; |
| 143 } |
| 144 |
| 66 static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) { | 145 static v8::Handle<v8::Value> GetNextRequestId(const v8::Arguments& args) { |
| 67 static int next_request_id = 0; | 146 static int next_request_id = 0; |
| 68 return v8::Integer::New(next_request_id++); | 147 return v8::Integer::New(next_request_id++); |
| 69 } | 148 } |
| 70 | 149 |
| 71 static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) { | 150 static v8::Handle<v8::Value> StartRequest(const v8::Arguments& args) { |
| 72 // Get the current RenderView so that we can send a routed IPC message from | 151 // Get the current RenderView so that we can send a routed IPC message from |
| 73 // the correct source. | 152 // the correct source. |
| 74 WebFrame* webframe = WebFrame::RetrieveFrameForCurrentContext(); | 153 WebFrame* webframe = WebFrame::RetrieveFrameForCurrentContext(); |
| 75 RenderView* renderview = GetRenderViewForCurrentContext(); | 154 RenderView* renderview = GetRenderViewForCurrentContext(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 96 | 175 |
| 97 v8::Extension* ExtensionProcessBindings::Get() { | 176 v8::Extension* ExtensionProcessBindings::Get() { |
| 98 return new ExtensionImpl(); | 177 return new ExtensionImpl(); |
| 99 } | 178 } |
| 100 | 179 |
| 101 void ExtensionProcessBindings::SetFunctionNames( | 180 void ExtensionProcessBindings::SetFunctionNames( |
| 102 const std::vector<std::string>& names) { | 181 const std::vector<std::string>& names) { |
| 103 ExtensionImpl::SetFunctionNames(names); | 182 ExtensionImpl::SetFunctionNames(names); |
| 104 } | 183 } |
| 105 | 184 |
| 185 void ExtensionProcessBindings::RegisterExtensionContext(WebFrame* frame) { |
| 186 frame->ExecuteScript(WebScriptSource(WebString::fromUTF8( |
| 187 "chrome.self.register_();"))); |
| 188 } |
| 189 |
| 106 void ExtensionProcessBindings::ExecuteResponseInFrame( | 190 void ExtensionProcessBindings::ExecuteResponseInFrame( |
| 107 CallContext *call, int request_id, bool success, | 191 CallContext *call, int request_id, bool success, |
| 108 const std::string& response, | 192 const std::string& response, |
| 109 const std::string& error) { | 193 const std::string& error) { |
| 110 std::string code = "chrome.handleResponse_("; | 194 std::string code = "chrome.handleResponse_("; |
| 111 code += IntToString(request_id); | 195 code += IntToString(request_id); |
| 112 | 196 |
| 113 code += ", '" + call->name_; | 197 code += ", '" + call->name_; |
| 114 | 198 |
| 115 if (success) | 199 if (success) |
| 116 code += "', true"; | 200 code += "', true"; |
| 117 else | 201 else |
| 118 code += "', false"; | 202 code += "', false"; |
| 119 | 203 |
| 120 code += ", '"; | 204 code += ", '"; |
| 121 size_t offset = code.length(); | 205 size_t offset = code.length(); |
| 122 code += response; | 206 code += response; |
| 123 ReplaceSubstringsAfterOffset(&code, offset, "\\", "\\\\"); | 207 ReplaceSubstringsAfterOffset(&code, offset, "\\", "\\\\"); |
| 124 ReplaceSubstringsAfterOffset(&code, offset, "'", "\\'"); | 208 ReplaceSubstringsAfterOffset(&code, offset, "'", "\\'"); |
| 125 code += "', '"; | 209 code += "', '"; |
| 126 offset = code.length(); | 210 offset = code.length(); |
| 127 code += error; | 211 code += error; |
| 128 ReplaceSubstringsAfterOffset(&code, offset, "\\", "\\\\"); | 212 ReplaceSubstringsAfterOffset(&code, offset, "\\", "\\\\"); |
| 129 ReplaceSubstringsAfterOffset(&code, offset, "'", "\\'"); | 213 ReplaceSubstringsAfterOffset(&code, offset, "'", "\\'"); |
| 130 code += "')"; | 214 code += "')"; |
| 131 | 215 |
| 132 call->frame_->ExecuteScript(WebScriptSource(WebString::fromUTF8(code))); | 216 call->frame_->ExecuteScript(WebScriptSource(WebString::fromUTF8(code))); |
| 133 } | 217 } |
| OLD | NEW |