Add Tizen-platform implementation of Cookie manager
authorArnaud Renevier <a.renevier@samsung.com>
Tue, 20 May 2014 21:09:30 +0000 (14:09 -0700)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
Change-Id: I74c5bd80c2c54b2fff7ced5639eb15159594888a

tizen_src/impl/API/ewk_cookie_manager_private.h [new file with mode: 0644]
tizen_src/impl/chromium-efl.gyp
tizen_src/impl/cookie_manager.cc [new file with mode: 0644]
tizen_src/impl/cookie_manager.h [new file with mode: 0644]

diff --git a/tizen_src/impl/API/ewk_cookie_manager_private.h b/tizen_src/impl/API/ewk_cookie_manager_private.h
new file mode 100644 (file)
index 0000000..d864caa
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this program; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ewk_cookie_manager_private_h
+#define ewk_cookie_manager_private_h
+
+#include "cookie_manager.h"
+
+namespace content {
+class URLRequestCOntextGetterEfl;
+}
+
+class Ewk_Cookie_Manager {
+ public:
+  static Ewk_Cookie_Manager* create(content::URLRequestContextGetterEfl* request_context_getter) {
+       return (new Ewk_Cookie_Manager(request_context_getter));
+  }
+
+  ~Ewk_Cookie_Manager() {}
+
+  CookieManager* cookieManager() const {
+    return cookie_manager_.get();
+  }
+
+ private:
+  explicit Ewk_Cookie_Manager(content::URLRequestContextGetterEfl* request_context_getter)
+    : cookie_manager_(new CookieManager(request_context_getter)) {}
+
+  scoped_refptr<CookieManager> cookie_manager_;
+};
+
+#endif // ewk_cookie_manager_private_h
index 92d3b9c..ff7c396 100644 (file)
@@ -41,6 +41,7 @@
       'EXE_DIR="<(exe_dir)"',
     ],
     'sources': [
+      'API/ewk_cookie_manager_private.h',
       'browser/device_sensors/data_fetcher_impl_tizen.cc',
       'browser/device_sensors/data_fetcher_impl_tizen.h',
       'browser/device_sensors/data_fetcher_shared_memory_tizen.cc',
@@ -97,6 +98,8 @@
       'components/clipboard/clipboard_helper_efl.h',
       'context_menu_controller_efl.cc',
       'context_menu_controller_efl.h',
+      'cookie_manager.cc',
+      'cookie_manager.h',
       'memory_purger.cc',
       'memory_purger.h',
       'network_delegate_efl.cc',
diff --git a/tizen_src/impl/cookie_manager.cc b/tizen_src/impl/cookie_manager.cc
new file mode 100644 (file)
index 0000000..e0a133a
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ */
+
+#include "cookie_manager.h"
+
+#include "utility"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/stl_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/synchronization/waitable_event.h"
+#include "content/public/browser/browser_thread.h"
+#include "eweb_context.h"
+#include "url_request_context_getter_efl.h"
+#include "net/base/net_errors.h"
+#include "net/base/static_cookie_policy.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_util.h"
+#include "net/cookies/parsed_cookie.h"
+#include "net/cookies/cookie_monster.h"
+#include "net/cookies/cookie_options.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
+
+#include <Eina.h>
+
+using content::BrowserThread;
+using net::CookieList;
+using net::CookieMonster;
+using base::AutoLock;
+
+namespace {
+
+void TriggerHostPolicyGetCallbackAsyncOnUIThread(Ewk_Cookie_Accept_Policy policy,
+                                                 CookieManager::AsyncPolicyGetCb callback,
+                                                 void *data) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (callback)
+    (*callback)(policy, NULL, data);
+}
+
+}
+
+class CookieManager::EwkGetHostCallback {
+ public:
+  EwkGetHostCallback(AsyncHostnamesGetCb callback, void* user_data)
+    : callback_(callback),
+      user_data_(user_data) {}
+
+  void TriggerCallback(const net::CookieList& cookies) {
+    Eina_List* hostnames = 0;
+    if (cookies.size()) {
+      net::CookieList::const_iterator it = cookies.begin();
+      while (it != cookies.end()) {
+        hostnames = eina_list_append(hostnames, eina_stringshare_add(it->Name().c_str()));
+        ++it;
+      }
+    }
+    (*callback_)(hostnames, NULL, user_data_);
+    void* item = 0;
+    EINA_LIST_FREE(hostnames, item)
+      eina_stringshare_del(static_cast<Eina_Stringshare*>(item));
+  }
+
+ private:
+       AsyncHostnamesGetCb callback_;
+    void* user_data_;
+};
+
+CookieManager::CookieManager(content::URLRequestContextGetterEfl* request_context_getter)
+    : is_clearing_(false),
+      request_context_getter_(request_context_getter),
+      cookie_policy_(EWK_COOKIE_ACCEPT_POLICY_ALWAYS)
+{
+}
+
+void CookieManager::DeleteCookiesAsync(const std::string& url,
+                                                                                          const std::string& cookie_name)
+{
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                                                   base::Bind(&CookieManager::DeleteCookiesOnIOThread,
+                                                                        this,
+                                                                        url,
+                                                                        cookie_name));
+}
+
+void CookieManager::DeleteCookiesOnIOThread(const std::string& url,
+                                                 const std::string& cookie_name) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  scoped_refptr<net::CookieMonster> cookie_monster =
+      request_context_getter_->GetURLRequestContext()->
+                 cookie_store()->GetCookieMonster();
+  if (url.empty()) { // Delete all cookies.
+    cookie_monster->DeleteAllAsync(net::CookieMonster::DeleteCallback());
+  }
+  GURL gurl(url);
+  if (!gurl.is_valid())
+       return;
+  if (cookie_name.empty()) {
+    // Delete all matching host cookies.
+    cookie_monster->DeleteAllForHostAsync(gurl,
+    net::CookieMonster::DeleteCallback());
+  } else {
+    // Delete all matching host and domain cookies.
+    cookie_monster->DeleteCookieAsync(gurl, cookie_name, base::Closure());
+  }
+}
+
+void CookieManager::SetStoragePath(const std::string& path,
+                                                                          bool persist_session_cookies,
+                                                                          bool file_storage_type) {
+       DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+       BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                                                       base::Bind(&CookieManager::SetStoragePathOnIOThread,
+                                                                        this,
+                                                                        path,
+                                                                        persist_session_cookies,
+                                                                        file_storage_type));
+}
+
+void CookieManager::GetAcceptPolicyAsync(AsyncPolicyGetCb callback, void *data) {
+  AutoLock lock(lock_);
+  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                                                 base::Bind(&TriggerHostPolicyGetCallbackAsyncOnUIThread,
+                                                                cookie_policy_,
+                                                                callback,
+                                                                data));
+}
+
+void CookieManager::GetHostNamesWithCookiesAsync(AsyncHostnamesGetCb callback, void *data) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  host_callback_queue_.push(new EwkGetHostCallback(callback, data));
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(&CookieManager::FetchCookiesOnIOThread, this));
+}
+
+void CookieManager::FetchCookiesOnIOThread() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  scoped_refptr<net::CookieMonster> cookie_monster =
+      request_context_getter_->GetURLRequestContext()->
+      cookie_store()->GetCookieMonster();
+  if (cookie_monster.get()) {
+    cookie_monster->GetAllCookiesAsync(base::Bind(&CookieManager::OnFetchComplete, this));
+  } else {
+    OnFetchComplete(net::CookieList());
+  }
+}
+
+void CookieManager::OnFetchComplete(const net::CookieList& cookies) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+                                                       base::Bind(&CookieManager::OnFetchComplete,
+                                                                          this,
+                                                                          cookies));
+    return;
+  }
+  if (!host_callback_queue_.empty()) {
+       EwkGetHostCallback* host_callback = host_callback_queue_.front();
+       if (host_callback) {
+      host_callback->TriggerCallback(cookies);
+      delete host_callback;
+       }
+       host_callback_queue_.pop();
+  }
+}
+
+void CookieManager::SetStoragePathOnIOThread(const std::string& path,
+                                             bool persist_session_cookies,
+                                             bool file_storage_type) { 
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  base::FilePath storage_path(path);
+  request_context_getter_->SetCookieStoragePath(storage_path, persist_session_cookies);
+}
+
+bool CookieManager::GetGlobalAllowAccess() {
+  AutoLock lock(lock_);
+  return (cookie_policy_ == EWK_COOKIE_ACCEPT_POLICY_ALWAYS);
+}
+
+void CookieManager::SetCookiePolicy(Ewk_Cookie_Accept_Policy policy) {
+  AutoLock lock(lock_);
+  cookie_policy_ = policy;
+}
+
+bool CookieManager::ShouldBlockThirdPartyCookies() {
+  AutoLock lock(lock_);
+  return (cookie_policy_ == EWK_COOKIE_ACCEPT_POLICY_NO_THIRD_PARTY);
+}
+
+bool CookieManager::AllowCookies(const GURL& url,
+                                 const GURL& first_party_url,
+                                 bool setting_cookie) {
+  if (GetGlobalAllowAccess())
+    return true;
+
+  if (ShouldBlockThirdPartyCookies()) {
+    net::StaticCookiePolicy policy(net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES);
+    int rv;
+    if (setting_cookie)
+      rv = policy.CanSetCookie(url, first_party_url);
+    else
+      rv = policy.CanGetCookies(url, first_party_url);
+
+    if (net::OK == rv)
+      return true;
+  }
+
+  return false;
+}
+
+bool CookieManager::OnCanGetCookies(const net::URLRequest& request,
+                                    const net::CookieList& cookie_list) {
+  return AllowCookies(request.url(), request.first_party_for_cookies(), false);
+}
+
+bool CookieManager::OnCanSetCookie(const net::URLRequest& request,
+                                   const std::string& cookie_line,
+                                   net::CookieOptions* options) {
+  return AllowCookies(request.url(), request.first_party_for_cookies(), true);
+}
+
+bool CookieManager::AllowGetCookie(const GURL& url,
+                                   const GURL& first_party,
+                                   const net::CookieList& cookie_list,
+                                   content::ResourceContext* context,
+                                   int render_process_id,
+                                   int render_frame_id) {
+  return AllowCookies(url, first_party, false);
+}
+
+bool CookieManager::AllowSetCookie(const GURL& url,
+                                   const GURL& first_party,
+                                   const std::string& cookie_line,
+                                   content::ResourceContext* context,
+                                   int render_process_id,
+                                   int render_frame_id,
+                                   net::CookieOptions* options) {
+  return AllowCookies(url, first_party, true);
+}
+
+void CookieManager::GetCookieValueOnIOThread(const GURL& host,
+                                             std::string* result,
+                                             base::WaitableEvent* completion) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  net::CookieOptions options;
+  options.set_include_httponly();
+  scoped_refptr<net::CookieMonster> cookie_monster =
+      request_context_getter_->GetURLRequestContext()->
+      cookie_store()->GetCookieMonster();
+  if (cookie_monster.get()) {
+    cookie_monster->GetCookiesWithOptionsAsync(host,
+                                               options,
+                                               base::Bind(&CookieManager::GetCookieValueCompleted,
+                                                          this,
+                                                          completion,
+                                                          result));
+  } else {
+    DCHECK(completion);
+    completion->Signal();
+  }
+}
+
+void CookieManager::GetCookieValueCompleted(base::WaitableEvent* completion,
+                                            std::string* result,
+                                            const std::string& value) {
+  *result = value;
+  DCHECK(completion);
+  completion->Signal();
+}
+
+std::string CookieManager::GetCookiesForURL(const std::string& url) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  std::string cookie_value;
+  base::WaitableEvent completion(false, false);
+  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                                                 base::Bind(&CookieManager::GetCookieValueOnIOThread,
+                                                                                this,
+                                                                                GURL(url),
+                                                                                &cookie_value,
+                                                                                &completion));
+  //allow wait temporarily
+  base::ThreadRestrictions::ScopedAllowWait allow_wait;
+  completion.Wait();
+  return cookie_value;
+}
diff --git a/tizen_src/impl/cookie_manager.h b/tizen_src/impl/cookie_manager.h
new file mode 100644 (file)
index 0000000..49e99a3
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2013 Samsung Electronics. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ */
+
+#ifndef cookie_manager_h
+#define cookie_manager_h
+
+#include "base/synchronization/lock.h"
+#include "base/basictypes.h"
+#include "public/ewk_cookie_manager.h"
+#include "url_request_context_getter_efl.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_options.h"
+#include "net/cookies/cookie_util.h"
+#include "url/gurl.h"
+
+#include <queue>
+#include <Eina.h>
+
+namespace content {
+class ResourceContext;
+}
+
+struct _Ewk_Error;
+
+class CookieManager 
+  : public base::RefCountedThreadSafe<CookieManager> {
+public:
+  typedef void (*AsyncPolicyGetCb)(Ewk_Cookie_Accept_Policy, _Ewk_Error*, void *);
+       typedef void (*AsyncHostnamesGetCb)(Eina_List*, _Ewk_Error*, void *);
+
+  explicit CookieManager(content::URLRequestContextGetterEfl* request_context_getter);
+  // Delete all cookies that match the specified parameters. If both |url| and
+       // values |cookie_name| are specified all host and domain cookies matching
+  // both will be deleted. If only |url| is specified all host cookies (but not
+  // domain cookies) irrespective of path will be deleted. If |url| is empty all
+  // cookies for all hosts and domains will be deleted. This method must be
+  // called on the IO thread.
+  void DeleteCookiesAsync(const std::string& url = std::string(),
+                          const std::string& cookie_name = std::string());
+  // Sets the directory path that will be used for storing cookie data. If
+  // |path| is empty data will be stored in memory only. Otherwise, data will be
+  // stored at the specified |path|. To persist session cookies (cookies without
+  // an expiry date or validity interval) set |persist_session_cookies| to true.
+  // Session cookies are generally intended to be transient and most Web browsers
+  // do not persist them. Returns false if cookies cannot be accessed.
+  void SetStoragePath(const std::string& path,
+                      bool persist_session_cookies,
+                      bool file_storage_type=true);
+  //get the accept policy asynchronous
+  void GetAcceptPolicyAsync(AsyncPolicyGetCb callback, void *data);
+  //get host name asynchronous
+  void GetHostNamesWithCookiesAsync(AsyncHostnamesGetCb callback, void *data);
+
+  // These manage the global access state shared across requests regardless of
+  // source (i.e. network or JavaScript).
+  bool GetGlobalAllowAccess();
+  void SetCookiePolicy(Ewk_Cookie_Accept_Policy policy);
+  // These are the functions called when operating over cookies from the
+  // network. See NetworkDelegate for further descriptions.
+  bool OnCanGetCookies(const net::URLRequest& request,
+                       const net::CookieList& cookie_list);
+  bool OnCanSetCookie(const net::URLRequest& request,
+                      const std::string& cookie_line,
+                      net::CookieOptions* options);
+
+  // These are the functions called when operating over cookies from the
+  // renderer. See ContentBrowserClient for further descriptions.
+  bool AllowGetCookie(const GURL& url,
+                      const GURL& first_party,
+                      const net::CookieList& cookie_list,
+                      content::ResourceContext* context,
+                      int render_process_id,
+                      int render_frame_id);
+  bool AllowSetCookie(const GURL& url,
+                      const GURL& first_party,
+                      const std::string& cookie_line,
+                      content::ResourceContext* context,
+                      int render_process_id,
+                      int render_frame_id,
+                      net::CookieOptions* options);
+  bool ShouldBlockThirdPartyCookies();
+  //This is synchronous call
+  std::string GetCookiesForURL(const std::string& url);
+
+protected:
+  friend class base::RefCountedThreadSafe<CookieManager>;
+
+  ~CookieManager()
+  {}
+
+private:
+  struct EwkGetHostCallback;
+
+  // Deletes cookie having host name. This must be called in IO thread.
+  void DeleteCookiesOnIOThread(const std::string& url,
+                                                                  const std::string& cookie_name) ;
+  void SetStoragePathOnIOThread(const std::string& path,
+                                                                   bool persist_session_cookies,
+                                bool file_storage_type);
+  bool AllowCookies(const GURL& url,
+                    const GURL& first_party_url,
+                    bool setting_cookie);
+  // Fetch the cookies. This must be called in the IO thread.
+  void FetchCookiesOnIOThread();
+  void OnFetchComplete(const net::CookieList& cookies);
+
+  void GetCookieValueOnIOThread(const GURL& host,
+                                std::string* result,
+                                base::WaitableEvent* completion);
+  void GetCookieValueCompleted(base::WaitableEvent* completion,
+                               std::string* result,
+                               const std::string& value);
+  // Indicates whether or not we're currently clearing information:
+  // it's true when ClearCookie() is called in the UI thread, and it's reset
+  // after we notify the callback in the UI thread.
+  // This only mutates on the UI thread.
+  bool is_clearing_;
+  scoped_refptr<content::URLRequestContextGetterEfl> request_context_getter_;
+  //cookie policy information
+  base::Lock lock_;
+  Ewk_Cookie_Accept_Policy cookie_policy_;
+  // This only mutates on the UI thread.
+  std::queue< EwkGetHostCallback* > host_callback_queue_;
+
+  DISALLOW_COPY_AND_ASSIGN(CookieManager);
+};
+
+#endif //cookie_manager_h