Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: chrome/renderer/extensions/chrome_app_bindings.cc

Issue 8113006: Add js api for hosted/pacakged apps to request notification authorization (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/callback_map.h"
15 #include "chrome/renderer/extensions/extension_dispatcher.h" 16 #include "chrome/renderer/extensions/extension_dispatcher.h"
16 #include "chrome/renderer/extensions/extension_helper.h" 17 #include "chrome/renderer/extensions/extension_helper.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
24 using extensions_v8_util::CallbackMap;
23 using WebKit::WebFrame; 25 using WebKit::WebFrame;
24 26
25 namespace { 27 namespace {
26 28
27 bool IsCheckoutURL(const std::string& url_spec) { 29 bool IsCheckoutURL(const std::string& url_spec) {
28 std::string checkout_url_prefix = 30 std::string checkout_url_prefix =
29 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 31 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
30 switches::kAppsCheckoutURL); 32 switches::kAppsCheckoutURL);
31 if (checkout_url_prefix.empty()) 33 if (checkout_url_prefix.empty())
32 checkout_url_prefix = "https://checkout.google.com/"; 34 checkout_url_prefix = "https://checkout.google.com/";
(...skipping 11 matching lines...) Expand all
44 if (!IsCheckoutURL(frame->document().url().spec())) { 46 if (!IsCheckoutURL(frame->document().url().spec())) {
45 std::string error("Access denied for URL: "); 47 std::string error("Access denied for URL: ");
46 error += frame->document().url().spec(); 48 error += frame->document().url().spec();
47 v8::ThrowException(v8::String::New(error.c_str())); 49 v8::ThrowException(v8::String::New(error.c_str()));
48 return false; 50 return false;
49 } 51 }
50 52
51 return true; 53 return true;
52 } 54 }
53 55
56 int g_next_request_id = 0;
57 base::LazyInstance<CallbackMap> 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
54 } // namespace 64 } // namespace
55 65
56 const char kAppExtensionName[] = "v8/ChromeApp"; 66 const char kAppExtensionName[] = "v8/ChromeApp";
57 67
58 namespace extensions_v8 { 68 namespace extensions_v8 {
59 69
60 class ChromeAppExtensionWrapper : public v8::Extension { 70 class ChromeAppExtensionWrapper : public v8::Extension {
61 public: 71 public:
62 explicit ChromeAppExtensionWrapper(ExtensionDispatcher* extension_dispatcher) 72 explicit ChromeAppExtensionWrapper(ExtensionDispatcher* extension_dispatcher)
63 : v8::Extension( 73 : v8::Extension(
64 kAppExtensionName, 74 kAppExtensionName,
65 "var chrome;" 75 "var chrome;"
66 "if (!chrome)" 76 "if (!chrome)"
67 " chrome = {};" 77 " chrome = {};"
68 "if (!chrome.app) {" 78 "if (!chrome.app) {"
69 " chrome.app = new function() {" 79 " chrome.app = new function() {"
70 " native function GetIsInstalled();" 80 " native function GetIsInstalled();"
71 " native function Install();" 81 " native function Install();"
72 " native function GetDetails();" 82 " native function GetDetails();"
73 " native function GetDetailsForFrame();" 83 " native function GetDetailsForFrame();"
84 " native function GetAppNotifyChannel();"
74 " this.__defineGetter__('isInstalled', GetIsInstalled);" 85 " this.__defineGetter__('isInstalled', GetIsInstalled);"
75 " this.install = Install;" 86 " this.install = Install;"
76 " this.getDetails = GetDetails;" 87 " this.getDetails = GetDetails;"
77 " this.getDetailsForFrame = GetDetailsForFrame;" 88 " this.getDetailsForFrame = GetDetailsForFrame;"
89 " this.experimental = {};"
Aaron Boodman 2011/10/03 22:07:43 Hm, is this checked against --enable-experimental-
asargent_no_longer_on_chrome 2011/10/04 00:43:20 Yep - the check is in ExtensionMessageHandler::OnG
90 " this.experimental.getNotificationChannel ="
91 " GetAppNotifyChannel;"
78 " };" 92 " };"
79 "}") { 93 "}") {
80 extension_dispatcher_ = extension_dispatcher; 94 extension_dispatcher_ = extension_dispatcher;
81 } 95 }
82 96
83 ~ChromeAppExtensionWrapper() { 97 ~ChromeAppExtensionWrapper() {
84 extension_dispatcher_ = NULL; 98 extension_dispatcher_ = NULL;
85 } 99 }
86 100
87 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( 101 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
88 v8::Handle<v8::String> name) { 102 v8::Handle<v8::String> name) {
89 if (name->Equals(v8::String::New("GetIsInstalled"))) { 103 if (name->Equals(v8::String::New("GetIsInstalled"))) {
90 return v8::FunctionTemplate::New(GetIsInstalled); 104 return v8::FunctionTemplate::New(GetIsInstalled);
91 } else if (name->Equals(v8::String::New("Install"))) { 105 } else if (name->Equals(v8::String::New("Install"))) {
92 return v8::FunctionTemplate::New(Install); 106 return v8::FunctionTemplate::New(Install);
93 } else if (name->Equals(v8::String::New("GetDetails"))) { 107 } else if (name->Equals(v8::String::New("GetDetails"))) {
94 return v8::FunctionTemplate::New(GetDetails); 108 return v8::FunctionTemplate::New(GetDetails);
95 } else if (name->Equals(v8::String::New("GetDetailsForFrame"))) { 109 } else if (name->Equals(v8::String::New("GetDetailsForFrame"))) {
96 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);
97 } else { 113 } else {
98 return v8::Handle<v8::FunctionTemplate>(); 114 return v8::Handle<v8::FunctionTemplate>();
99 } 115 }
100 } 116 }
101 117
102 static v8::Handle<v8::Value> GetIsInstalled(const v8::Arguments& args) { 118 static v8::Handle<v8::Value> GetIsInstalled(const v8::Arguments& args) {
103 WebFrame* frame = WebFrame::frameForCurrentContext(); 119 WebFrame* frame = WebFrame::frameForCurrentContext();
104 if (!frame) 120 if (!frame)
105 return v8::False(); 121 return v8::False();
106 122
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 return v8::Null(); 188 return v8::Null();
173 189
174 scoped_ptr<DictionaryValue> manifest_copy( 190 scoped_ptr<DictionaryValue> manifest_copy(
175 extension->manifest_value()->DeepCopy()); 191 extension->manifest_value()->DeepCopy());
176 manifest_copy->SetString("id", extension->id()); 192 manifest_copy->SetString("id", extension->id());
177 V8ValueConverter converter; 193 V8ValueConverter converter;
178 return converter.ToV8Value(manifest_copy.get(), 194 return converter.ToV8Value(manifest_copy.get(),
179 frame->mainWorldScriptContext()); 195 frame->mainWorldScriptContext());
180 } 196 }
181 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
182 static ExtensionDispatcher* extension_dispatcher_; 245 static ExtensionDispatcher* extension_dispatcher_;
183 }; 246 };
184 247
185 ExtensionDispatcher* ChromeAppExtensionWrapper::extension_dispatcher_; 248 ExtensionDispatcher* ChromeAppExtensionWrapper::extension_dispatcher_;
186 249
187 v8::Extension* ChromeAppExtension::Get( 250 v8::Extension* ChromeAppExtension::Get(
188 ExtensionDispatcher* extension_dispatcher) { 251 ExtensionDispatcher* extension_dispatcher) {
189 return new ChromeAppExtensionWrapper(extension_dispatcher); 252 return new ChromeAppExtensionWrapper(extension_dispatcher);
190 } 253 }
191 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
192 } // namespace extensions_v8 268 } // namespace extensions_v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698