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/chrome_webstore_bindings.h" | 5 #include "chrome/renderer/extensions/chrome_webstore_bindings.h" |
6 | 6 |
7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "chrome/common/extensions/extension.h" | 9 #include "chrome/common/extensions/extension.h" |
| 10 #include "chrome/renderer/extensions/callback_map.h" |
10 #include "chrome/renderer/extensions/extension_helper.h" | 11 #include "chrome/renderer/extensions/extension_helper.h" |
11 #include "content/renderer/render_view.h" | 12 #include "content/renderer/render_view.h" |
12 #include "googleurl/src/gurl.h" | 13 #include "googleurl/src/gurl.h" |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h" |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNodeList.h" |
18 #include "v8/include/v8.h" | 19 #include "v8/include/v8.h" |
19 | 20 |
| 21 using extensions_v8_util::CallbackMap; |
20 using WebKit::WebDocument; | 22 using WebKit::WebDocument; |
21 using WebKit::WebElement; | 23 using WebKit::WebElement; |
22 using WebKit::WebFrame; | 24 using WebKit::WebFrame; |
23 using WebKit::WebNode; | 25 using WebKit::WebNode; |
24 using WebKit::WebNodeList; | 26 using WebKit::WebNodeList; |
25 | 27 |
26 namespace { | 28 namespace { |
27 | 29 |
28 const char kWebstoreV8ExtensionName[] = "v8/ChromeWebstore"; | 30 const char kWebstoreV8ExtensionName[] = "v8/ChromeWebstore"; |
29 | 31 |
(...skipping 12 matching lines...) Expand all Loading... |
42 const char kNoWebstoreItemLinkFoundError[] = | 44 const char kNoWebstoreItemLinkFoundError[] = |
43 "No Chrome Web Store item link found."; | 45 "No Chrome Web Store item link found."; |
44 const char kInvalidWebstoreItemUrlError[] = | 46 const char kInvalidWebstoreItemUrlError[] = |
45 "Invalid Chrome Web Store item URL."; | 47 "Invalid Chrome Web Store item URL."; |
46 | 48 |
47 // chrome.webstore.install() calls generate an install ID so that the install's | 49 // chrome.webstore.install() calls generate an install ID so that the install's |
48 // callbacks may be fired when the browser notifies us of install completion | 50 // callbacks may be fired when the browser notifies us of install completion |
49 // (successful or not) via HandleInstallResponse. | 51 // (successful or not) via HandleInstallResponse. |
50 int g_next_install_id = 0; | 52 int g_next_install_id = 0; |
51 | 53 |
52 // Callbacks are kept track of in maps keyed by install ID. Values are weak | |
53 // references to functions. Entries are automatically removed when functions | |
54 // get garbage collected. | |
55 typedef std::map<int, v8::Persistent<v8::Function> > CallbackMap; | |
56 | |
57 base::LazyInstance<CallbackMap> g_success_callbacks(base::LINKER_INITIALIZED); | 54 base::LazyInstance<CallbackMap> g_success_callbacks(base::LINKER_INITIALIZED); |
58 base::LazyInstance<CallbackMap> g_failure_callbacks(base::LINKER_INITIALIZED); | 55 base::LazyInstance<CallbackMap> g_failure_callbacks(base::LINKER_INITIALIZED); |
59 | 56 |
60 // Extra data to be passed to MakeWeak/RemoveFromCallbackMap to know which entry | |
61 // to remove from which map. | |
62 struct CallbackMapData { | |
63 CallbackMap* callback_map; | |
64 int install_id; | |
65 }; | |
66 | |
67 // Disposes of a callback function and its corresponding entry in the callback | |
68 // map. | |
69 static void RemoveFromCallbackMap(v8::Persistent<v8::Value> context, | |
70 void* data) { | |
71 CallbackMapData* callback_map_data = static_cast<CallbackMapData*>(data); | |
72 callback_map_data->callback_map->erase(callback_map_data->install_id); | |
73 delete callback_map_data; | |
74 context.Dispose(); | |
75 } | |
76 | |
77 // Adds |callback_param| (assumed to be a function) to |callback_map| under the | |
78 // |install_id| key. Will be removed from the map when the value is about to be | |
79 // GCed. | |
80 static void AddToCallbackMap(int install_id, | |
81 v8::Local<v8::Value> callback_param, | |
82 CallbackMap* callback_map) { | |
83 CHECK(callback_param->IsFunction()); | |
84 CallbackMapData* callback_map_data = new CallbackMapData(); | |
85 callback_map_data->install_id = install_id; | |
86 callback_map_data->callback_map = callback_map; | |
87 | |
88 v8::Local<v8::Function> function = v8::Function::Cast(*callback_param); | |
89 v8::Persistent<v8::Function> wrapper = | |
90 v8::Persistent<v8::Function>::New(function); | |
91 (*callback_map)[install_id] = wrapper; | |
92 wrapper.MakeWeak(callback_map_data, RemoveFromCallbackMap); | |
93 } | |
94 | |
95 } // anonymous namespace | 57 } // anonymous namespace |
96 | 58 |
97 class ExtensionImpl : public v8::Extension { | 59 class ExtensionImpl : public v8::Extension { |
98 public: | 60 public: |
99 ExtensionImpl() : | 61 ExtensionImpl() : |
100 v8::Extension( | 62 v8::Extension( |
101 kWebstoreV8ExtensionName, | 63 kWebstoreV8ExtensionName, |
102 "var chrome = chrome || {};" | 64 "var chrome = chrome || {};" |
103 "if (!chrome.webstore) {" | 65 "if (!chrome.webstore) {" |
104 " chrome.webstore = new function() {" | 66 " chrome.webstore = new function() {" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 std::string error; | 102 std::string error; |
141 if (!GetWebstoreItemIdFromFrame( | 103 if (!GetWebstoreItemIdFromFrame( |
142 frame, preferred_store_link_url, &webstore_item_id, &error)) { | 104 frame, preferred_store_link_url, &webstore_item_id, &error)) { |
143 v8::ThrowException(v8::String::New(error.c_str())); | 105 v8::ThrowException(v8::String::New(error.c_str())); |
144 return v8::Undefined(); | 106 return v8::Undefined(); |
145 } | 107 } |
146 | 108 |
147 int install_id = g_next_install_id++; | 109 int install_id = g_next_install_id++; |
148 if (args.Length() >= 2 && !args[1]->IsUndefined()) { | 110 if (args.Length() >= 2 && !args[1]->IsUndefined()) { |
149 if (args[1]->IsFunction()) { | 111 if (args[1]->IsFunction()) { |
150 AddToCallbackMap(install_id, args[1], g_success_callbacks.Pointer()); | 112 g_success_callbacks.Get().Add(install_id, v8::Function::Cast(*args[1])); |
151 } else { | 113 } else { |
152 v8::ThrowException(v8::String::New(kSuccessCallbackNotAFunctionError)); | 114 v8::ThrowException(v8::String::New(kSuccessCallbackNotAFunctionError)); |
153 return v8::Undefined(); | 115 return v8::Undefined(); |
154 } | 116 } |
155 } | 117 } |
156 if (args.Length() >= 3 && !args[2]->IsUndefined()) { | 118 if (args.Length() >= 3 && !args[2]->IsUndefined()) { |
157 if (args[2]->IsFunction()) { | 119 if (args[2]->IsFunction()) { |
158 AddToCallbackMap(install_id, args[2], g_failure_callbacks.Pointer()); | 120 g_failure_callbacks.Get().Add(install_id, v8::Function::Cast(*args[2])); |
159 } else { | 121 } else { |
160 v8::ThrowException(v8::String::New(kFailureCallbackNotAFunctionError)); | 122 v8::ThrowException(v8::String::New(kFailureCallbackNotAFunctionError)); |
161 return v8::Undefined(); | 123 return v8::Undefined(); |
162 } | 124 } |
163 } | 125 } |
164 | 126 |
165 ExtensionHelper* helper = ExtensionHelper::Get(render_view); | 127 ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
166 helper->InlineWebstoreInstall( | 128 helper->InlineWebstoreInstall( |
167 install_id, webstore_item_id, frame->document().url()); | 129 install_id, webstore_item_id, frame->document().url()); |
168 return v8::Undefined(); | 130 return v8::Undefined(); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 | 225 |
264 // static | 226 // static |
265 v8::Extension* ChromeWebstoreExtension::Get() { | 227 v8::Extension* ChromeWebstoreExtension::Get() { |
266 return new ExtensionImpl(); | 228 return new ExtensionImpl(); |
267 } | 229 } |
268 | 230 |
269 // static | 231 // static |
270 void ChromeWebstoreExtension::HandleInstallResponse(int install_id, | 232 void ChromeWebstoreExtension::HandleInstallResponse(int install_id, |
271 bool success, | 233 bool success, |
272 const std::string& error) { | 234 const std::string& error) { |
273 CallbackMap* callback_map = | 235 CallbackMap& callback_map = |
274 success ? g_success_callbacks.Pointer() : g_failure_callbacks.Pointer(); | 236 success ? g_success_callbacks.Get() : g_failure_callbacks.Get(); |
275 CallbackMap::iterator iter = callback_map->find(install_id); | |
276 | 237 |
277 if (iter == callback_map->end() || iter->second.IsEmpty()) return; | 238 v8::Persistent<v8::Function> function = callback_map.Remove(install_id); |
278 const v8::Persistent<v8::Function>& function = (*iter).second; | 239 if (function.IsEmpty()) |
| 240 return; |
279 | 241 |
280 v8::HandleScope handle_scope; | 242 v8::HandleScope handle_scope; |
281 v8::Context::Scope context_scope(function->CreationContext()); | 243 v8::Context::Scope context_scope(function->CreationContext()); |
282 v8::Handle<v8::Value> argv[1]; | 244 v8::Handle<v8::Value> argv[1]; |
283 argv[0] = v8::String::New(error.c_str()); | 245 argv[0] = v8::String::New(error.c_str()); |
284 function->Call(v8::Object::New(), arraysize(argv), argv); | 246 function->Call(v8::Object::New(), arraysize(argv), argv); |
285 | |
286 callback_map->erase(iter); | |
287 } | 247 } |
OLD | NEW |