| 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/extension_helper.h" | 10 #include "chrome/renderer/extensions/extension_helper.h" |
| 11 #include "chrome/renderer/weak_v8_function_map.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 |
| 20 using WebKit::WebDocument; | 21 using WebKit::WebDocument; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 42 const char kNoWebstoreItemLinkFoundError[] = | 43 const char kNoWebstoreItemLinkFoundError[] = |
| 43 "No Chrome Web Store item link found."; | 44 "No Chrome Web Store item link found."; |
| 44 const char kInvalidWebstoreItemUrlError[] = | 45 const char kInvalidWebstoreItemUrlError[] = |
| 45 "Invalid Chrome Web Store item URL."; | 46 "Invalid Chrome Web Store item URL."; |
| 46 | 47 |
| 47 // chrome.webstore.install() calls generate an install ID so that the install's | 48 // 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 | 49 // callbacks may be fired when the browser notifies us of install completion |
| 49 // (successful or not) via HandleInstallResponse. | 50 // (successful or not) via HandleInstallResponse. |
| 50 int g_next_install_id = 0; | 51 int g_next_install_id = 0; |
| 51 | 52 |
| 52 // Callbacks are kept track of in maps keyed by install ID. Values are weak | 53 base::LazyInstance<WeakV8FunctionMap> g_success_callbacks( |
| 53 // references to functions. Entries are automatically removed when functions | 54 base::LINKER_INITIALIZED); |
| 54 // get garbage collected. | 55 base::LazyInstance<WeakV8FunctionMap> g_failure_callbacks( |
| 55 typedef std::map<int, v8::Persistent<v8::Function> > CallbackMap; | 56 base::LINKER_INITIALIZED); |
| 56 | |
| 57 base::LazyInstance<CallbackMap> g_success_callbacks(base::LINKER_INITIALIZED); | |
| 58 base::LazyInstance<CallbackMap> g_failure_callbacks(base::LINKER_INITIALIZED); | |
| 59 | |
| 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 | 57 |
| 95 } // anonymous namespace | 58 } // anonymous namespace |
| 96 | 59 |
| 97 class ExtensionImpl : public v8::Extension { | 60 class ExtensionImpl : public v8::Extension { |
| 98 public: | 61 public: |
| 99 ExtensionImpl() : | 62 ExtensionImpl() : |
| 100 v8::Extension( | 63 v8::Extension( |
| 101 kWebstoreV8ExtensionName, | 64 kWebstoreV8ExtensionName, |
| 102 "var chrome = chrome || {};" | 65 "var chrome = chrome || {};" |
| 103 "if (!chrome.webstore) {" | 66 "if (!chrome.webstore) {" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 std::string error; | 103 std::string error; |
| 141 if (!GetWebstoreItemIdFromFrame( | 104 if (!GetWebstoreItemIdFromFrame( |
| 142 frame, preferred_store_link_url, &webstore_item_id, &error)) { | 105 frame, preferred_store_link_url, &webstore_item_id, &error)) { |
| 143 v8::ThrowException(v8::String::New(error.c_str())); | 106 v8::ThrowException(v8::String::New(error.c_str())); |
| 144 return v8::Undefined(); | 107 return v8::Undefined(); |
| 145 } | 108 } |
| 146 | 109 |
| 147 int install_id = g_next_install_id++; | 110 int install_id = g_next_install_id++; |
| 148 if (args.Length() >= 2 && !args[1]->IsUndefined()) { | 111 if (args.Length() >= 2 && !args[1]->IsUndefined()) { |
| 149 if (args[1]->IsFunction()) { | 112 if (args[1]->IsFunction()) { |
| 150 AddToCallbackMap(install_id, args[1], g_success_callbacks.Pointer()); | 113 g_success_callbacks.Get().Add(install_id, v8::Function::Cast(*args[1])); |
| 151 } else { | 114 } else { |
| 152 v8::ThrowException(v8::String::New(kSuccessCallbackNotAFunctionError)); | 115 v8::ThrowException(v8::String::New(kSuccessCallbackNotAFunctionError)); |
| 153 return v8::Undefined(); | 116 return v8::Undefined(); |
| 154 } | 117 } |
| 155 } | 118 } |
| 156 if (args.Length() >= 3 && !args[2]->IsUndefined()) { | 119 if (args.Length() >= 3 && !args[2]->IsUndefined()) { |
| 157 if (args[2]->IsFunction()) { | 120 if (args[2]->IsFunction()) { |
| 158 AddToCallbackMap(install_id, args[2], g_failure_callbacks.Pointer()); | 121 g_failure_callbacks.Get().Add(install_id, v8::Function::Cast(*args[2])); |
| 159 } else { | 122 } else { |
| 160 v8::ThrowException(v8::String::New(kFailureCallbackNotAFunctionError)); | 123 v8::ThrowException(v8::String::New(kFailureCallbackNotAFunctionError)); |
| 161 return v8::Undefined(); | 124 return v8::Undefined(); |
| 162 } | 125 } |
| 163 } | 126 } |
| 164 | 127 |
| 165 ExtensionHelper* helper = ExtensionHelper::Get(render_view); | 128 ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
| 166 helper->InlineWebstoreInstall( | 129 helper->InlineWebstoreInstall( |
| 167 install_id, webstore_item_id, frame->document().url()); | 130 install_id, webstore_item_id, frame->document().url()); |
| 168 return v8::Undefined(); | 131 return v8::Undefined(); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 | 226 |
| 264 // static | 227 // static |
| 265 v8::Extension* ChromeWebstoreExtension::Get() { | 228 v8::Extension* ChromeWebstoreExtension::Get() { |
| 266 return new ExtensionImpl(); | 229 return new ExtensionImpl(); |
| 267 } | 230 } |
| 268 | 231 |
| 269 // static | 232 // static |
| 270 void ChromeWebstoreExtension::HandleInstallResponse(int install_id, | 233 void ChromeWebstoreExtension::HandleInstallResponse(int install_id, |
| 271 bool success, | 234 bool success, |
| 272 const std::string& error) { | 235 const std::string& error) { |
| 273 CallbackMap* callback_map = | 236 WeakV8FunctionMap& callback_map = |
| 274 success ? g_success_callbacks.Pointer() : g_failure_callbacks.Pointer(); | 237 success ? g_success_callbacks.Get() : g_failure_callbacks.Get(); |
| 275 CallbackMap::iterator iter = callback_map->find(install_id); | |
| 276 | 238 |
| 277 if (iter == callback_map->end() || iter->second.IsEmpty()) return; | 239 v8::Persistent<v8::Function> function = callback_map.Remove(install_id); |
| 278 const v8::Persistent<v8::Function>& function = (*iter).second; | 240 if (function.IsEmpty()) |
| 241 return; |
| 279 | 242 |
| 280 v8::HandleScope handle_scope; | 243 v8::HandleScope handle_scope; |
| 281 v8::Context::Scope context_scope(function->CreationContext()); | 244 v8::Context::Scope context_scope(function->CreationContext()); |
| 282 v8::Handle<v8::Value> argv[1]; | 245 v8::Handle<v8::Value> argv[1]; |
| 283 argv[0] = v8::String::New(error.c_str()); | 246 argv[0] = v8::String::New(error.c_str()); |
| 284 function->Call(v8::Object::New(), arraysize(argv), argv); | 247 function->Call(v8::Object::New(), arraysize(argv), argv); |
| 285 | |
| 286 callback_map->erase(iter); | |
| 287 } | 248 } |
| OLD | NEW |