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 |