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