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_app_bindings.h" | 5 #include "chrome/renderer/extensions/chrome_app_bindings.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/json/json_writer.h" | 8 #include "base/json/json_writer.h" |
9 #include "base/string16.h" | 9 #include "base/string16.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "chrome/common/chrome_switches.h" | 13 #include "chrome/common/chrome_switches.h" |
14 #include "chrome/common/extensions/extension_set.h" | 14 #include "chrome/common/extensions/extension_set.h" |
15 #include "chrome/renderer/extensions/extension_dispatcher.h" | 15 #include "chrome/renderer/extensions/extension_dispatcher.h" |
16 #include "chrome/renderer/extensions/extension_helper.h" | 16 #include "chrome/renderer/extensions/extension_helper.h" |
| 17 #include "chrome/renderer/weak_v8_function_map.h" |
17 #include "content/public/renderer/v8_value_converter.h" | 18 #include "content/public/renderer/v8_value_converter.h" |
18 #include "content/renderer/render_view.h" | 19 #include "content/renderer/render_view.h" |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
21 #include "v8/include/v8.h" | 22 #include "v8/include/v8.h" |
22 | 23 |
23 using WebKit::WebFrame; | 24 using WebKit::WebFrame; |
24 using content::V8ValueConverter; | 25 using content::V8ValueConverter; |
25 | 26 |
26 namespace { | 27 namespace { |
(...skipping 18 matching lines...) Expand all Loading... |
45 if (!IsCheckoutURL(frame->document().url().spec())) { | 46 if (!IsCheckoutURL(frame->document().url().spec())) { |
46 std::string error("Access denied for URL: "); | 47 std::string error("Access denied for URL: "); |
47 error += frame->document().url().spec(); | 48 error += frame->document().url().spec(); |
48 v8::ThrowException(v8::String::New(error.c_str())); | 49 v8::ThrowException(v8::String::New(error.c_str())); |
49 return false; | 50 return false; |
50 } | 51 } |
51 | 52 |
52 return true; | 53 return true; |
53 } | 54 } |
54 | 55 |
| 56 int g_next_request_id = 0; |
| 57 base::LazyInstance<WeakV8FunctionMap> g_callbacks(base::LINKER_INITIALIZED); |
| 58 |
| 59 const char* kMissingClientIdError = "Missing clientId parameter"; |
| 60 const char* kInvalidClientIdError = "Invalid clientId"; |
| 61 const char* kCallbackNotAFunctionError = |
| 62 "The callback that was passed is not a function"; |
| 63 |
55 } // namespace | 64 } // namespace |
56 | 65 |
57 const char kAppExtensionName[] = "v8/ChromeApp"; | 66 const char kAppExtensionName[] = "v8/ChromeApp"; |
58 | 67 |
59 namespace extensions_v8 { | 68 namespace extensions_v8 { |
60 | 69 |
61 class ChromeAppExtensionWrapper : public v8::Extension { | 70 class ChromeAppExtensionWrapper : public v8::Extension { |
62 public: | 71 public: |
63 explicit ChromeAppExtensionWrapper(ExtensionDispatcher* extension_dispatcher) | 72 explicit ChromeAppExtensionWrapper(ExtensionDispatcher* extension_dispatcher) |
64 : v8::Extension( | 73 : v8::Extension( |
65 kAppExtensionName, | 74 kAppExtensionName, |
66 "var chrome;" | 75 "var chrome;" |
67 "if (!chrome)" | 76 "if (!chrome)" |
68 " chrome = {};" | 77 " chrome = {};" |
69 "if (!chrome.app) {" | 78 "if (!chrome.app) {" |
70 " chrome.app = new function() {" | 79 " chrome.app = new function() {" |
71 " native function GetIsInstalled();" | 80 " native function GetIsInstalled();" |
72 " native function Install();" | 81 " native function Install();" |
73 " native function GetDetails();" | 82 " native function GetDetails();" |
74 " native function GetDetailsForFrame();" | 83 " native function GetDetailsForFrame();" |
| 84 " native function GetAppNotifyChannel();" |
75 " this.__defineGetter__('isInstalled', GetIsInstalled);" | 85 " this.__defineGetter__('isInstalled', GetIsInstalled);" |
76 " this.install = Install;" | 86 " this.install = Install;" |
77 " this.getDetails = GetDetails;" | 87 " this.getDetails = GetDetails;" |
78 " this.getDetailsForFrame = GetDetailsForFrame;" | 88 " this.getDetailsForFrame = GetDetailsForFrame;" |
| 89 " this.experimental = {};" |
| 90 " this.experimental.getNotificationChannel =" |
| 91 " GetAppNotifyChannel;" |
79 " };" | 92 " };" |
80 "}") { | 93 "}") { |
81 extension_dispatcher_ = extension_dispatcher; | 94 extension_dispatcher_ = extension_dispatcher; |
82 } | 95 } |
83 | 96 |
84 ~ChromeAppExtensionWrapper() { | 97 ~ChromeAppExtensionWrapper() { |
85 extension_dispatcher_ = NULL; | 98 extension_dispatcher_ = NULL; |
86 } | 99 } |
87 | 100 |
88 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 101 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
89 v8::Handle<v8::String> name) { | 102 v8::Handle<v8::String> name) { |
90 if (name->Equals(v8::String::New("GetIsInstalled"))) { | 103 if (name->Equals(v8::String::New("GetIsInstalled"))) { |
91 return v8::FunctionTemplate::New(GetIsInstalled); | 104 return v8::FunctionTemplate::New(GetIsInstalled); |
92 } else if (name->Equals(v8::String::New("Install"))) { | 105 } else if (name->Equals(v8::String::New("Install"))) { |
93 return v8::FunctionTemplate::New(Install); | 106 return v8::FunctionTemplate::New(Install); |
94 } else if (name->Equals(v8::String::New("GetDetails"))) { | 107 } else if (name->Equals(v8::String::New("GetDetails"))) { |
95 return v8::FunctionTemplate::New(GetDetails); | 108 return v8::FunctionTemplate::New(GetDetails); |
96 } else if (name->Equals(v8::String::New("GetDetailsForFrame"))) { | 109 } else if (name->Equals(v8::String::New("GetDetailsForFrame"))) { |
97 return v8::FunctionTemplate::New(GetDetailsForFrame); | 110 return v8::FunctionTemplate::New(GetDetailsForFrame); |
| 111 } else if (name->Equals(v8::String::New("GetAppNotifyChannel"))) { |
| 112 return v8::FunctionTemplate::New(GetAppNotifyChannel); |
98 } else { | 113 } else { |
99 return v8::Handle<v8::FunctionTemplate>(); | 114 return v8::Handle<v8::FunctionTemplate>(); |
100 } | 115 } |
101 } | 116 } |
102 | 117 |
103 static v8::Handle<v8::Value> GetIsInstalled(const v8::Arguments& args) { | 118 static v8::Handle<v8::Value> GetIsInstalled(const v8::Arguments& args) { |
104 WebFrame* frame = WebFrame::frameForCurrentContext(); | 119 WebFrame* frame = WebFrame::frameForCurrentContext(); |
105 if (!frame) | 120 if (!frame) |
106 return v8::False(); | 121 return v8::False(); |
107 | 122 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 return v8::Null(); | 188 return v8::Null(); |
174 | 189 |
175 scoped_ptr<DictionaryValue> manifest_copy( | 190 scoped_ptr<DictionaryValue> manifest_copy( |
176 extension->manifest_value()->DeepCopy()); | 191 extension->manifest_value()->DeepCopy()); |
177 manifest_copy->SetString("id", extension->id()); | 192 manifest_copy->SetString("id", extension->id()); |
178 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); | 193 scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); |
179 return converter->ToV8Value(manifest_copy.get(), | 194 return converter->ToV8Value(manifest_copy.get(), |
180 frame->mainWorldScriptContext()); | 195 frame->mainWorldScriptContext()); |
181 } | 196 } |
182 | 197 |
| 198 static v8::Handle<v8::Value> GetAppNotifyChannel(const v8::Arguments& args) { |
| 199 WebFrame* frame = WebFrame::frameForCurrentContext(); |
| 200 if (!frame || !frame->view()) |
| 201 return v8::Undefined(); |
| 202 |
| 203 RenderView* render_view = RenderView::FromWebView(frame->view()); |
| 204 if (!render_view) |
| 205 return v8::Undefined(); |
| 206 |
| 207 if (g_next_request_id < 0) |
| 208 return v8::Undefined(); |
| 209 int request_id = g_next_request_id++; |
| 210 |
| 211 // Read the required 'clientId' value out of the object at args[0]. |
| 212 std::string client_id; |
| 213 if (args.Length() < 1 || !args[0]->IsObject()) { |
| 214 v8::ThrowException(v8::String::New(kMissingClientIdError)); |
| 215 return v8::Undefined(); |
| 216 } |
| 217 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(args[0]); |
| 218 v8::Local<v8::String> client_id_key = v8::String::New("clientId"); |
| 219 if (obj->Has(client_id_key)) { |
| 220 v8::String::Utf8Value id_value(obj->Get(client_id_key)); |
| 221 if (id_value.length() > 0) |
| 222 client_id = std::string(*id_value); |
| 223 } |
| 224 if (client_id.empty()) { |
| 225 v8::ThrowException(v8::String::New(kInvalidClientIdError)); |
| 226 return v8::Undefined(); |
| 227 } |
| 228 |
| 229 // Hang on to the callback if there was one. |
| 230 if (args.Length() >= 2) { |
| 231 if (args[1]->IsFunction()) { |
| 232 g_callbacks.Get().Add(request_id, v8::Function::Cast(*args[1])); |
| 233 } else { |
| 234 v8::ThrowException(v8::String::New(kCallbackNotAFunctionError)); |
| 235 return v8::Undefined(); |
| 236 } |
| 237 } |
| 238 |
| 239 ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
| 240 helper->GetAppNotifyChannel( |
| 241 request_id, frame->document().url(), client_id); |
| 242 return v8::Undefined(); |
| 243 } |
| 244 |
183 static ExtensionDispatcher* extension_dispatcher_; | 245 static ExtensionDispatcher* extension_dispatcher_; |
184 }; | 246 }; |
185 | 247 |
186 ExtensionDispatcher* ChromeAppExtensionWrapper::extension_dispatcher_; | 248 ExtensionDispatcher* ChromeAppExtensionWrapper::extension_dispatcher_; |
187 | 249 |
188 v8::Extension* ChromeAppExtension::Get( | 250 v8::Extension* ChromeAppExtension::Get( |
189 ExtensionDispatcher* extension_dispatcher) { | 251 ExtensionDispatcher* extension_dispatcher) { |
190 return new ChromeAppExtensionWrapper(extension_dispatcher); | 252 return new ChromeAppExtensionWrapper(extension_dispatcher); |
191 } | 253 } |
192 | 254 |
| 255 void ChromeAppExtension::HandleGetAppNotifyChannelResponse( |
| 256 int request_id, const std::string& channel_id, const std::string& error) { |
| 257 v8::Persistent<v8::Function> function = g_callbacks.Get().Remove(request_id); |
| 258 if (function.IsEmpty()) |
| 259 return; |
| 260 v8::HandleScope handle_scope; |
| 261 v8::Context::Scope context_scope(function->CreationContext()); |
| 262 v8::Handle<v8::Value> argv[2]; |
| 263 argv[0] = v8::String::New(channel_id.c_str()); |
| 264 argv[1] = v8::String::New(error.c_str()); |
| 265 function->Call(v8::Object::New(), arraysize(argv), argv); |
| 266 } |
| 267 |
193 } // namespace extensions_v8 | 268 } // namespace extensions_v8 |
OLD | NEW |