Add initial cookie changed event support
authorKevin Sawicki <kevinsawicki@gmail.com>
Wed, 21 Sep 2016 23:24:03 +0000 (16:24 -0700)
committerKevin Sawicki <kevinsawicki@gmail.com>
Thu, 29 Sep 2016 16:16:29 +0000 (09:16 -0700)
atom/browser/api/atom_api_cookies.cc
atom/browser/api/atom_api_cookies.h
atom/browser/api/atom_api_session.cc
atom/browser/atom_browser_context.cc
atom/browser/atom_browser_context.h
atom/browser/net/atom_cookie_delegate.cc [new file with mode: 0644]
atom/browser/net/atom_cookie_delegate.h [new file with mode: 0644]
filenames.gypi
lib/browser/api/session.js

index 86cc598..a04ace5 100644 (file)
@@ -20,6 +20,7 @@
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
 
+using atom::AtomCookieDelegate;
 using content::BrowserThread;
 
 namespace mate {
@@ -54,6 +55,29 @@ struct Converter<net::CanonicalCookie> {
   }
 };
 
+
+template<>
+struct Converter<AtomCookieDelegate::ChangeCause> {
+  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
+                                   const AtomCookieDelegate::ChangeCause& val) {
+    switch (val) {
+      case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPLICIT:
+        return mate::StringToV8(isolate, "explicit");
+      case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_OVERWRITE:
+        return mate::StringToV8(isolate, "overwrite");
+      case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPIRED:
+        return mate::StringToV8(isolate, "expired");
+      case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EVICTED:
+        return mate::StringToV8(isolate, "evicted");
+      case AtomCookieDelegate::ChangeCause::CHANGE_COOKIE_EXPIRED_OVERWRITE:
+        return mate::StringToV8(isolate, "expired-overwrite");
+      default:
+        return mate::StringToV8(isolate, "unknown");
+    }
+  }
+};
+
+
 }  // namespace mate
 
 namespace atom {
@@ -206,11 +230,14 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
 
 Cookies::Cookies(v8::Isolate* isolate,
                  AtomBrowserContext* browser_context)
-      : request_context_getter_(browser_context->url_request_context_getter()) {
+      : request_context_getter_(browser_context->url_request_context_getter()),
+        cookie_delegate_(browser_context->cookie_delegate()) {
   Init(isolate);
+  cookie_delegate_->AddObserver(this);
 }
 
 Cookies::~Cookies() {
+  cookie_delegate_->RemoveObserver(this);
 }
 
 void Cookies::Get(const base::DictionaryValue& filter,
@@ -239,6 +266,15 @@ void Cookies::Set(const base::DictionaryValue& details,
       base::Bind(SetCookieOnIO, getter, Passed(&copied), callback));
 }
 
+void Cookies::OnCookieChanged(const net::CanonicalCookie& cookie,
+                              bool removed,
+                              AtomCookieDelegate::ChangeCause cause) {
+  v8::Locker locker(isolate());
+  v8::HandleScope handle_scope(isolate());
+  Emit("changed", cookie, cause, removed);
+}
+
+
 // static
 mate::Handle<Cookies> Cookies::Create(
     v8::Isolate* isolate,
index 5f60cb7..5c29ceb 100644 (file)
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "atom/browser/api/trackable_object.h"
+#include "atom/browser/net/atom_cookie_delegate.h"
 #include "base/callback.h"
 #include "native_mate/handle.h"
 #include "net/cookies/canonical_cookie.h"
@@ -26,7 +27,8 @@ class AtomBrowserContext;
 
 namespace api {
 
-class Cookies : public mate::TrackableObject<Cookies> {
+class Cookies : public mate::TrackableObject<Cookies>,
+                public AtomCookieDelegate::Observer {
  public:
   enum Error {
     SUCCESS,
@@ -52,8 +54,14 @@ class Cookies : public mate::TrackableObject<Cookies> {
               const base::Closure& callback);
   void Set(const base::DictionaryValue& details, const SetCallback& callback);
 
+  // AtomCookieDelegate::Observer:
+  void OnCookieChanged(const net::CanonicalCookie& cookie,
+                       bool removed,
+                       AtomCookieDelegate::ChangeCause cause) override;
+
  private:
   net::URLRequestContextGetter* request_context_getter_;
+  AtomCookieDelegate* cookie_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(Cookies);
 };
index 4540509..96fcca5 100644 (file)
@@ -49,6 +49,7 @@
 #include "net/url_request/url_request_context_getter.h"
 #include "ui/base/l10n/l10n_util.h"
 
+using atom::api::Cookies;
 using content::BrowserThread;
 using content::StoragePartition;
 
@@ -335,7 +336,7 @@ void OnClearStorageDataDone(const base::Closure& callback) {
 Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
     : devtools_network_emulation_client_id_(base::GenerateGUID()),
       browser_context_(browser_context) {
-  // Observe DownloadManger to get download notifications.
+  // Observe DownloadManager to get download notifications.
   content::BrowserContext::GetDownloadManager(browser_context)->
       AddObserver(this);
 
@@ -521,7 +522,7 @@ void Session::GetBlobData(
 
 v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
   if (cookies_.IsEmpty()) {
-    auto handle = atom::api::Cookies::Create(isolate, browser_context());
+    auto handle = Cookies::Create(isolate, browser_context());
     cookies_.Reset(isolate, handle.ToV8());
   }
   return v8::Local<v8::Value>::New(isolate, cookies_);
@@ -631,6 +632,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
   v8::Isolate* isolate = context->GetIsolate();
   mate::Dictionary dict(isolate, exports);
   dict.Set("Session", Session::GetConstructor(isolate)->GetFunction());
+  dict.Set("Cookies", Cookies::GetConstructor(isolate)->GetFunction());
   dict.SetMethod("fromPartition", &FromPartition);
 }
 
index 0b81469..63c8c81 100644 (file)
@@ -71,7 +71,8 @@ AtomBrowserContext::AtomBrowserContext(
     const std::string& partition, bool in_memory,
     const base::DictionaryValue& options)
     : brightray::BrowserContext(partition, in_memory),
-      network_delegate_(new AtomNetworkDelegate) {
+      network_delegate_(new AtomNetworkDelegate),
+      cookie_delegate_(new AtomCookieDelegate) {
   // Construct user agent string.
   Browser* browser = Browser::Get();
   std::string name = RemoveWhitespace(browser->GetName());
@@ -107,6 +108,10 @@ net::NetworkDelegate* AtomBrowserContext::CreateNetworkDelegate() {
   return network_delegate_;
 }
 
+net::CookieMonsterDelegate* AtomBrowserContext::CreateCookieDelegate() {
+  return cookie_delegate();
+}
+
 std::string AtomBrowserContext::GetUserAgent() {
   return user_agent_;
 }
index 23d8c64..0ff1cc6 100644 (file)
@@ -8,7 +8,9 @@
 #include <string>
 #include <vector>
 
+#include "atom/browser/net/atom_cookie_delegate.h"
 #include "brightray/browser/browser_context.h"
+#include "net/cookies/cookie_monster.h"
 
 namespace atom {
 
@@ -31,6 +33,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
 
   // brightray::URLRequestContextGetter::Delegate:
   net::NetworkDelegate* CreateNetworkDelegate() override;
+  net::CookieMonsterDelegate* CreateCookieDelegate() override;
   std::string GetUserAgent() override;
   std::unique_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
       content::ProtocolHandlerMap* protocol_handlers) override;
@@ -50,6 +53,9 @@ class AtomBrowserContext : public brightray::BrowserContext {
 
   AtomBlobReader* GetBlobReader();
   AtomNetworkDelegate* network_delegate() const { return network_delegate_; }
+  AtomCookieDelegate* cookie_delegate() const {
+    return cookie_delegate_.get();
+  }
 
  protected:
   AtomBrowserContext(const std::string& partition, bool in_memory,
@@ -66,6 +72,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
 
   // Managed by brightray::BrowserContext.
   AtomNetworkDelegate* network_delegate_;
+  scoped_refptr<AtomCookieDelegate> cookie_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
 };
diff --git a/atom/browser/net/atom_cookie_delegate.cc b/atom/browser/net/atom_cookie_delegate.cc
new file mode 100644 (file)
index 0000000..5024a34
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/browser/net/atom_cookie_delegate.h"
+
+#include "content/public/browser/browser_thread.h"
+
+namespace atom {
+
+AtomCookieDelegate::AtomCookieDelegate() {
+}
+
+AtomCookieDelegate::~AtomCookieDelegate() {
+}
+
+void AtomCookieDelegate::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void AtomCookieDelegate::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void AtomCookieDelegate::NotifyObservers(
+  const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) {
+  FOR_EACH_OBSERVER(Observer,
+                    observers_,
+                    OnCookieChanged(cookie, removed, cause));
+}
+
+void AtomCookieDelegate::OnCookieChanged(
+    const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) {
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&AtomCookieDelegate::NotifyObservers,
+                 this, cookie, removed, cause));
+}
+
+}  // namespace atom
diff --git a/atom/browser/net/atom_cookie_delegate.h b/atom/browser/net/atom_cookie_delegate.h
new file mode 100644 (file)
index 0000000..20acbd3
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (c) 2016 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_BROWSER_NET_ATOM_COOKIE_DELEGATE_H_
+#define ATOM_BROWSER_NET_ATOM_COOKIE_DELEGATE_H_
+
+#include "base/observer_list.h"
+#include "net/cookies/cookie_monster.h"
+
+namespace atom {
+
+class AtomCookieDelegate : public net::CookieMonsterDelegate {
+ public:
+  AtomCookieDelegate();
+  ~AtomCookieDelegate() override;
+
+  class Observer {
+   public:
+    virtual void OnCookieChanged(const net::CanonicalCookie& cookie,
+                                 bool removed,
+                                 ChangeCause cause) {}
+   protected:
+    virtual ~Observer() {}
+  };
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  // net::CookieMonsterDelegate:
+  void OnCookieChanged(const net::CanonicalCookie& cookie,
+                       bool removed,
+                       ChangeCause cause) override;
+
+
+ private:
+  base::ObserverList<Observer> observers_;
+
+  void NotifyObservers(const net::CanonicalCookie& cookie,
+                       bool removed,
+                       ChangeCause cause);
+
+  DISALLOW_COPY_AND_ASSIGN(AtomCookieDelegate);
+};
+
+}   // namespace atom
+
+#endif  // ATOM_BROWSER_NET_ATOM_COOKIE_DELEGATE_H_
index d8b3ede..9c4b42f 100644 (file)
       'atom/browser/net/asar/url_request_asar_job.h',
       'atom/browser/net/atom_cert_verifier.cc',
       'atom/browser/net/atom_cert_verifier.h',
+      'atom/browser/net/atom_cookie_delegate.cc',
+      'atom/browser/net/atom_cookie_delegate.h',
       'atom/browser/net/atom_network_delegate.cc',
       'atom/browser/net/atom_network_delegate.h',
       'atom/browser/net/atom_ssl_config_service.cc',
index af553e4..ac47244 100644 (file)
@@ -1,6 +1,6 @@
 const {EventEmitter} = require('events')
 const {app} = require('electron')
-const {fromPartition, Session} = process.atomBinding('session')
+const {fromPartition, Session, Cookies} = process.atomBinding('session')
 
 // Public API.
 Object.defineProperties(exports, {
@@ -15,6 +15,7 @@ Object.defineProperties(exports, {
 })
 
 Object.setPrototypeOf(Session.prototype, EventEmitter.prototype)
+Object.setPrototypeOf(Cookies.prototype, EventEmitter.prototype)
 
 Session.prototype._init = function () {
   app.emit('session-created', this)