Chromium Code Reviews| Index: chrome/renderer/extensions/chrome_app_bindings.cc |
| diff --git a/chrome/renderer/extensions/chrome_app_bindings.cc b/chrome/renderer/extensions/chrome_app_bindings.cc |
| index f2b8638e4152b562836dae5c0a2c2b476dacb4db..b748bc76c6355d7af1385fe1ada7865317cb5efe 100644 |
| --- a/chrome/renderer/extensions/chrome_app_bindings.cc |
| +++ b/chrome/renderer/extensions/chrome_app_bindings.cc |
| @@ -12,6 +12,7 @@ |
| #include "base/values.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/extension_set.h" |
| +#include "chrome/renderer/extensions/callback_map.h" |
| #include "chrome/renderer/extensions/extension_dispatcher.h" |
| #include "chrome/renderer/extensions/extension_helper.h" |
| #include "content/renderer/render_view.h" |
| @@ -20,6 +21,7 @@ |
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| #include "v8/include/v8.h" |
| +using extensions_v8_util::CallbackMap; |
| using WebKit::WebFrame; |
| namespace { |
| @@ -51,6 +53,14 @@ bool CheckAccessToAppDetails() { |
| return true; |
| } |
| +int g_next_request_id = 0; |
| +base::LazyInstance<CallbackMap> g_callbacks(base::LINKER_INITIALIZED); |
| + |
| +const char* kMissingClientIdError = "Missing clientId parameter"; |
| +const char* kInvalidClientIdError = "Invalid clientId"; |
| +const char* kCallbackNotAFunctionError = |
| + "The callback that was passed is not a function"; |
| + |
| } // namespace |
| const char kAppExtensionName[] = "v8/ChromeApp"; |
| @@ -71,10 +81,14 @@ class ChromeAppExtensionWrapper : public v8::Extension { |
| " native function Install();" |
| " native function GetDetails();" |
| " native function GetDetailsForFrame();" |
| + " native function GetAppNotifyChannel();" |
| " this.__defineGetter__('isInstalled', GetIsInstalled);" |
| " this.install = Install;" |
| " this.getDetails = GetDetails;" |
| " this.getDetailsForFrame = GetDetailsForFrame;" |
| + " 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
|
| + " this.experimental.getNotificationChannel =" |
| + " GetAppNotifyChannel;" |
| " };" |
| "}") { |
| extension_dispatcher_ = extension_dispatcher; |
| @@ -94,6 +108,8 @@ class ChromeAppExtensionWrapper : public v8::Extension { |
| return v8::FunctionTemplate::New(GetDetails); |
| } else if (name->Equals(v8::String::New("GetDetailsForFrame"))) { |
| return v8::FunctionTemplate::New(GetDetailsForFrame); |
| + } else if (name->Equals(v8::String::New("GetAppNotifyChannel"))) { |
| + return v8::FunctionTemplate::New(GetAppNotifyChannel); |
| } else { |
| return v8::Handle<v8::FunctionTemplate>(); |
| } |
| @@ -179,6 +195,53 @@ class ChromeAppExtensionWrapper : public v8::Extension { |
| frame->mainWorldScriptContext()); |
| } |
| + static v8::Handle<v8::Value> GetAppNotifyChannel(const v8::Arguments& args) { |
| + WebFrame* frame = WebFrame::frameForCurrentContext(); |
| + if (!frame || !frame->view()) |
| + return v8::Undefined(); |
| + |
| + RenderView* render_view = RenderView::FromWebView(frame->view()); |
| + if (!render_view) |
| + return v8::Undefined(); |
| + |
| + if (g_next_request_id < 0) |
| + return v8::Undefined(); |
| + int request_id = g_next_request_id++; |
| + |
| + // Read the required 'clientId' value out of the object at args[0]. |
| + std::string client_id; |
| + if (args.Length() < 1 || !args[0]->IsObject()) { |
| + v8::ThrowException(v8::String::New(kMissingClientIdError)); |
| + return v8::Undefined(); |
| + } |
| + v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(args[0]); |
| + v8::Local<v8::String> client_id_key = v8::String::New("clientId"); |
| + if (obj->Has(client_id_key)) { |
| + v8::String::Utf8Value id_value(obj->Get(client_id_key)); |
| + if (id_value.length() > 0) |
| + client_id = std::string(*id_value); |
| + } |
| + if (client_id.empty()) { |
| + v8::ThrowException(v8::String::New(kInvalidClientIdError)); |
| + return v8::Undefined(); |
| + } |
| + |
| + // Hang on to the callback if there was one. |
| + if (args.Length() >= 2) { |
| + if (args[1]->IsFunction()) { |
| + g_callbacks.Get().Add(request_id, v8::Function::Cast(*args[1])); |
| + } else { |
| + v8::ThrowException(v8::String::New(kCallbackNotAFunctionError)); |
| + return v8::Undefined(); |
| + } |
| + } |
| + |
| + ExtensionHelper* helper = ExtensionHelper::Get(render_view); |
| + helper->GetAppNotifyChannel( |
| + request_id, frame->document().url(), client_id); |
| + return v8::Undefined(); |
| + } |
| + |
| static ExtensionDispatcher* extension_dispatcher_; |
| }; |
| @@ -189,4 +252,17 @@ v8::Extension* ChromeAppExtension::Get( |
| return new ChromeAppExtensionWrapper(extension_dispatcher); |
| } |
| +void ChromeAppExtension::HandleGetAppNotifyChannelResponse( |
| + int request_id, const std::string& channel_id, const std::string& error) { |
| + v8::Persistent<v8::Function> function = g_callbacks.Get().Remove(request_id); |
| + if (function.IsEmpty()) |
| + return; |
| + v8::HandleScope handle_scope; |
| + v8::Context::Scope context_scope(function->CreationContext()); |
| + v8::Handle<v8::Value> argv[2]; |
| + argv[0] = v8::String::New(channel_id.c_str()); |
| + argv[1] = v8::String::New(error.c_str()); |
| + function->Call(v8::Object::New(), arraysize(argv), argv); |
| +} |
| + |
| } // namespace extensions_v8 |