Remember registered schemes.
authorCheng Zhao <zcbenz@gmail.com>
Sat, 24 Aug 2013 08:38:19 +0000 (16:38 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Sat, 24 Aug 2013 08:38:19 +0000 (16:38 +0800)
browser/api/atom_api_protocol.cc
browser/api/atom_api_protocol.h
spec/api/protocol.coffee [new file with mode: 0644]

index 871ae4b..41d2233 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "browser/api/atom_api_protocol.h"
 
+#include "content/public/browser/browser_thread.h"
 #include "net/url_request/url_request_job_manager.h"
 #include "vendor/node/src/node.h"
 
@@ -11,17 +12,55 @@ namespace atom {
 
 namespace api {
 
+Protocol::HandlersMap Protocol::handlers_;
+
 // static
 v8::Handle<v8::Value> Protocol::RegisterProtocol(const v8::Arguments& args) {
+  std::string scheme(*v8::String::Utf8Value(args[0]));
+  if (handlers_.find(scheme) != handlers_.end())
+    return node::ThrowError("The scheme is already registered");
+
+  // Store the handler in a map.
+  if (!args[1]->IsFunction())
+    return node::ThrowError("Handler must be a function");
+  handlers_[scheme] = v8::Persistent<v8::Function>::New(
+      node::node_isolate, v8::Handle<v8::Function>::Cast(args[1]));
+
+  content::BrowserThread::PostTask(content::BrowserThread::IO,
+                                   FROM_HERE, 
+                                   base::Bind(&RegisterProtocolInIO, scheme));
+
   return v8::Undefined();
 }
 
 // static
 v8::Handle<v8::Value> Protocol::UnregisterProtocol(const v8::Arguments& args) {
+  std::string scheme(*v8::String::Utf8Value(args[0]));
+
+  // Erase the handler from map.
+  HandlersMap::iterator it(handlers_.find(scheme));
+  if (it == handlers_.end())
+    return node::ThrowError("The scheme has not been registered");
+  handlers_.erase(it);
+
+  content::BrowserThread::PostTask(content::BrowserThread::IO,
+                                   FROM_HERE, 
+                                   base::Bind(&UnregisterProtocolInIO, scheme));
+
   return v8::Undefined();
 }
 
 // static
+void Protocol::RegisterProtocolInIO(const std::string& scheme) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+}
+
+// static
+void Protocol::UnregisterProtocolInIO(const std::string& scheme) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+}
+
+// static
 void Protocol::Initialize(v8::Handle<v8::Object> target) {
   node::SetMethod(target, "registerProtocol", RegisterProtocol);
   node::SetMethod(target, "unregisterProtocol", UnregisterProtocol);
index 11b48f0..4f53c1d 100644 (file)
@@ -5,6 +5,9 @@
 #ifndef ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
 #define ATOM_BROWSER_API_ATOM_API_PROTOCOL_H_
 
+#include <string>
+#include <map>
+
 #include "base/basictypes.h"
 #include "v8/include/v8.h"
 
@@ -20,6 +23,12 @@ class Protocol {
   static v8::Handle<v8::Value> RegisterProtocol(const v8::Arguments& args);
   static v8::Handle<v8::Value> UnregisterProtocol(const v8::Arguments& args);
 
+  static void RegisterProtocolInIO(const std::string& scheme);
+  static void UnregisterProtocolInIO(const std::string& scheme);
+
+  typedef std::map<std::string, v8::Persistent<v8::Function>> HandlersMap;
+  static HandlersMap handlers_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(Protocol);
 };
 
diff --git a/spec/api/protocol.coffee b/spec/api/protocol.coffee
new file mode 100644 (file)
index 0000000..332afec
--- /dev/null
@@ -0,0 +1,15 @@
+assert = require 'assert'
+protocol = require('remote').require 'protocol'
+
+describe 'protocol API', ->
+  describe 'protocol.registerProtocol', ->
+    it 'throws error when scheme is already registered', ->
+      register = -> protocol.registerProtocol('test', ->)
+      register()
+      assert.throws register, /The scheme is already registered/
+      protocol.unregisterProtocol 'test'
+
+  describe 'protocol.unregisterProtocol', ->
+    it 'throws error when scheme does not exist', ->
+      unregister = -> protocol.unregisterProtocol 'test'
+      assert.throws unregister, /The scheme has not been registered/