[M108 Migration][Certificate] Bring up certificate 32/287532/3
authorayush.k123 <ayush.k123@samsung.com>
Tue, 31 Jan 2023 03:54:28 +0000 (09:24 +0530)
committerBot Blink <blinkbot@samsung.com>
Tue, 31 Jan 2023 13:48:59 +0000 (13:48 +0000)
Migrate certificate related code from M94

References: https://review.tizen.org/gerrit/277727/

Change-Id: Ie9a8dc27fcc5b0eaf0f0f0d5dcc5f271992d3963
Signed-off-by: Ayush Kumar <ayush.k123@samsung.com>
27 files changed:
base/files/file_enumerator.h
base/files/file_enumerator_posix.cc
net/cert/cert_database.cc
net/cert/cert_database.h
tizen_src/ewk/efl_integration/BUILD.gn
tizen_src/ewk/efl_integration/browser_context_efl.cc
tizen_src/ewk/efl_integration/browser_context_efl.h
tizen_src/ewk/efl_integration/content_browser_client_efl.cc
tizen_src/ewk/efl_integration/content_browser_client_efl.h
tizen_src/ewk/efl_integration/eweb_context.cc
tizen_src/ewk/efl_integration/eweb_context.h
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h
tizen_src/ewk/efl_integration/eweb_view_callbacks.h
tizen_src/ewk/efl_integration/private/ewk_certificate_info_private.h [new file with mode: 0644]
tizen_src/ewk/efl_integration/private/ewk_certificate_private.cc [new file with mode: 0644]
tizen_src/ewk/efl_integration/private/ewk_certificate_private.h
tizen_src/ewk/efl_integration/private/ewk_context_private.cc
tizen_src/ewk/efl_integration/private/ewk_context_private.h
tizen_src/ewk/efl_integration/public/ewk_certificate.cc
tizen_src/ewk/efl_integration/public/ewk_context.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.h
tizen_src/ewk/unittest/BUILD.gn
tizen_src/ewk/unittest/utc_blink_ewk_certificate_policy_decision_error_get_func.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_certificate_policy_decision_from_main_frame_get_func.cpp [new file with mode: 0644]
tizen_src/ewk/unittest/utc_blink_ewk_certificate_policy_decision_suspend_func.cpp

index cbcfcaf..3c7e4da 100644 (file)
@@ -180,6 +180,10 @@ class BASE_EXPORT FileEnumerator {
   // error code reflecting why enumeration was stopped early.
   File::Error GetError() const { return error_; }
 
+#if BUILDFLAG(IS_EFL)
+  void SetExtMatchToFlag();
+#endif
+
  private:
   // Returns true if the given path should be skipped in enumeration.
   bool ShouldSkip(const FilePath& path);
@@ -215,6 +219,9 @@ class BASE_EXPORT FileEnumerator {
   int file_type_;
   FilePath::StringType pattern_;
   const FolderSearchPolicy folder_search_policy_;
+#if BUILDFLAG(IS_EFL)
+  int fnmatch_flag_;
+#endif
   const ErrorPolicy error_policy_;
   File::Error error_ = File::FILE_OK;
 
index e329b88..dd293f0 100644 (file)
@@ -119,6 +119,9 @@ FileEnumerator::FileEnumerator(const FilePath& root_path,
       file_type_(file_type),
       pattern_(pattern),
       folder_search_policy_(folder_search_policy),
+#if BUILDFLAG(IS_EFL)
+      fnmatch_flag_(FNM_NOESCAPE),
+#endif
       error_policy_(error_policy) {
   // INCLUDE_DOT_DOT must not be specified if recursive.
   DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
@@ -141,6 +144,12 @@ FileEnumerator::FileEnumerator(const FilePath& root_path,
 
 FileEnumerator::~FileEnumerator() = default;
 
+#if BUILDFLAG(IS_EFL)
+void FileEnumerator::SetExtMatchToFlag() {
+  fnmatch_flag_ |= FNM_EXTMATCH;
+}
+#endif
+
 FilePath FileEnumerator::Next() {
   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
 
@@ -255,7 +264,11 @@ FileEnumerator::FileInfo FileEnumerator::GetInfo() const {
 
 bool FileEnumerator::IsPatternMatched(const FilePath& path) const {
   return pattern_.empty() ||
+#if BUILDFLAG(IS_EFL)
+         !fnmatch(pattern_.c_str(), path.value().c_str(), fnmatch_flag_);
+#else
          !fnmatch(pattern_.c_str(), path.value().c_str(), FNM_NOESCAPE);
+#endif
 }
 
 }  // namespace base
index 728d9e4..2d63299 100644 (file)
 #include "net/log/net_log.h"
 #include "net/log/net_log_values.h"
 
+#if BUILDFLAG(IS_EFL)
+#include <cert.h>
+#include <certdb.h>
+#include <pk11pub.h>
+#include <secmod.h>
+
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "net/base/net_errors.h"
+#include "net/cert/x509_util_nss.h"
+#endif
+
 namespace net {
 
 // static
@@ -20,6 +32,50 @@ CertDatabase* CertDatabase::GetInstance() {
                          base::LeakySingletonTraits<CertDatabase>>::get();
 }
 
+#if BUILDFLAG(IS_EFL)
+int CertDatabase::ImportCACert(CERTCertificate* cert) {
+  if (!CERT_IsCACert(cert, NULL))
+    return ERR_IMPORT_CA_CERT_NOT_CA;
+
+  if (cert->isperm)
+    return ERR_IMPORT_CERT_ALREADY_EXISTS;
+
+  // CK_INVALID_HANDLE in case of CA cert
+  CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
+  // Get PersistentStorage for PK11
+  crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot());
+
+  std::string nickname =
+      x509_util::GetDefaultUniqueNickname(cert, CA_CERT, slot.get());
+
+  {
+    base::AutoLock lock(lock_);
+    SECStatus rv;
+    rv = PK11_ImportCert(slot.get(), cert, key, nickname.c_str(),
+                         PR_FALSE /*ignored*/);
+    if (rv != SECSuccess) {
+      LOG(ERROR) << "Couldn't import CA certificate: \"" << nickname
+                 << "\", error code: " << PORT_GetError();
+      return ERR_IMPORT_CA_CERT_FAILED;
+    } else {
+      // We have to set trust separately:
+      CERTCertTrust trust = {CERTDB_VALID_CA, CERTDB_VALID_CA, CERTDB_VALID_CA};
+      trust.sslFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;
+      rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust);
+      if (rv != SECSuccess) {
+        LOG(ERROR) << "Couldn't set trust for CA certificate: \"" << nickname
+                   << "\", error code: " << PORT_GetError();
+        return ERR_IMPORT_CA_CERT_FAILED;
+      }
+    }
+  }
+
+  LOG(INFO) << "Imported CA certificate: \"" << nickname << "\"";
+
+  return OK;
+}
+#endif
+
 void CertDatabase::AddObserver(Observer* observer) {
   observer_list_->AddObserver(observer);
 }
index 03c4f6a..1fe4785 100644 (file)
 #include "build/build_config.h"
 #include "net/base/net_export.h"
 
+#if BUILDFLAG(IS_EFL)
+#include "base/synchronization/lock.h"
+
+typedef struct CERTCertificateStr CERTCertificate;
+#endif
+
 namespace base {
 template <typename T> struct DefaultSingletonTraits;
 
@@ -58,6 +64,16 @@ class NET_EXPORT CertDatabase {
   CertDatabase(const CertDatabase&) = delete;
   CertDatabase& operator=(const CertDatabase&) = delete;
 
+#if BUILDFLAG(IS_EFL)
+  // Store CA certificate in persistent storage.
+  // Returns OK if successful, or network error codes if there was a problem
+  // importing:
+  //   * ERR_IMPORT_CA_CERT_FAILED
+  //   * ERR_IMPORT_CA_CERT_NOT_CA
+  //   * ERR_IMPORT_CERT_ALREADY_EXISTS
+  int ImportCACert(CERTCertificate* cert);
+#endif
+
   // Registers |observer| to receive notifications of certificate changes.  The
   // thread on which this is called is the thread on which |observer| will be
   // called back with notifications.
@@ -94,6 +110,10 @@ class NET_EXPORT CertDatabase {
   friend class Notifier;
   raw_ptr<Notifier> notifier_ = nullptr;
 #endif
+
+#if BUILDFLAG(IS_EFL)
+  base::Lock lock_;
+#endif
 };
 
 }  // namespace net
index 7797280..56e33c0 100755 (executable)
@@ -376,6 +376,8 @@ shared_library("chromium-ewk") {
     "private/ewk_autofill_profile_private.h",
     "private/ewk_back_forward_list_private.cc",
     "private/ewk_back_forward_list_private.h",
+    "private/ewk_certificate_info_private.h",
+    "private/ewk_certificate_private.cc",
     "private/ewk_certificate_private.h",
     "private/ewk_console_message_private.h",
     "private/ewk_context_form_autofill_profile_private.cc",
index 2c50667..4a31804 100644 (file)
@@ -5,8 +5,10 @@
 #include "browser_context_efl.h"
 
 #include "base/bind.h"
+#include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
 #include "base/path_service.h"
+#include "base/strings/string_split.h"
 #include "base/synchronization/waitable_event.h"
 #include "browser/autofill/autocomplete_history_manager_factory.h"
 #include "browser/autofill/personal_data_manager_factory.h"
@@ -28,6 +30,8 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "eweb_context.h"
+#include "net/cert/cert_database.h"
+#include "net/cert/x509_util_nss.h"
 #include "network_delegate_efl.h"
 #include "permission_controller_delegate_efl.h"
 
@@ -41,6 +45,20 @@ void HandleReadError(PersistentPrefStore::PrefReadError error) {
   NOTIMPLEMENTED();
 }
 
+net::ScopedCERTCertificateList GetCertListFromFile(
+    const base::FilePath& file_path) {
+  std::string cert_data;
+  net::ScopedCERTCertificateList cert_list;
+  if (base::ReadFileToString(file_path, &cert_data)) {
+    cert_list = net::x509_util::CreateCERTCertificateListFromBytes(
+        cert_data.data(), cert_data.size(), net::X509Certificate::FORMAT_AUTO);
+  } else {
+    LOG(ERROR) << "Could not read file \"" << file_path.AsUTF8Unsafe()
+               << "\" for loading CA certs. Please check permissions!";
+  }
+  return cert_list;
+}
+
 }  // namespace
 
 namespace content {
@@ -221,41 +239,56 @@ void BrowserContextEfl::CreateNetworkDelegate() {
       new net::NetworkDelegateEfl(web_context_->cookieManager()->GetWeakPtr()));
 }
 
-void BrowserContextEfl::SetCertificate(const char* certificate_file) {
-  base::FilePath* certificate_path = new base::FilePath(certificate_file);
+void BrowserContextEfl::SetCertificatePath(
+    const std::string& certificate_path) {
+  certificate_path_ = certificate_path;
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-#if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
-  BrowserThread::PostTask(
-      BrowserThread::FILE, FROM_HERE,
-      base::BindOnce(&BrowserContextEfl::ReadCertificateAndAdd,
-                     base::Owned(certificate_path)));
-#endif
-}
-
-void BrowserContextEfl::ReadCertificateAndAdd(base::FilePath* file_path) {
-#if !defined(EWK_BRINGUP)  // FIXME: m94 bringup
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-  std::string cert_contents;
-  base::ReadFileToString(*file_path, &cert_contents);
-  scoped_refptr<net::X509Certificate> cert(
-      net::X509Certificate::CreateFromBytes(cert_contents.c_str(),
-                                            cert_contents.size()));
-  if (!cert.get()) {
-    DLOG(ERROR) << "User certificate could not be parsed.";
+  auto* storage_partition = BrowserContext::GetDefaultStoragePartition();
+  if (!storage_partition)
     return;
-  }
-  int err_code = net::CertDatabase::GetInstance()->CheckUserCert(cert.get());
-  if (net::OK != err_code) {
-    DLOG(ERROR) << "User certificate is not valid. Error code : " << err_code;
-    return;
-  }
-  err_code = net::CertDatabase::GetInstance()->AddUserCert(cert.get());
-  if (net::OK != err_code) {
-    DLOG(ERROR) << "User certificate could not be added. Error code : "
-                << err_code;
+
+  auto* file_system_context = storage_partition->GetFileSystemContext();
+  if (!file_system_context)
     return;
+
+  file_system_context->default_file_task_runner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&BrowserContextEfl::ReadCertificateAndAdd,
+                     base::Owned(new std::string(certificate_path))));
+}
+
+void BrowserContextEfl::ReadCertificateAndAdd(
+    const std::string* certificate_path) {
+  std::vector<std::string> paths = base::SplitString(
+      *certificate_path, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+  for (const auto& path : paths) {
+    base::FilePath file_path(path);
+    base::File file(file_path, base::File::FLAG_OPEN);
+    base::File::Info file_info;
+    // Check if path is accessible
+    if (file.IsValid() && file.GetInfo(&file_info)) {
+      if (file_info.is_directory) {
+        base::FileEnumerator files(
+            file_path, true,
+            base::FileEnumerator::FILES | base::FileEnumerator::SHOW_SYM_LINKS,
+            "@(*.crt|*.pem)");
+        files.SetExtMatchToFlag();
+        for (base::FilePath cert_file = files.Next(); !cert_file.empty();
+             cert_file = files.Next()) {
+          for (const auto& ca_cert : GetCertListFromFile(cert_file)) {
+            net::CertDatabase::GetInstance()->ImportCACert(ca_cert.get());
+          }
+        }
+      } else {
+        for (const auto& ca_cert : GetCertListFromFile(file_path)) {
+          net::CertDatabase::GetInstance()->ImportCACert(ca_cert.get());
+        }
+      }
+    } else {  // Stat returned non-zero, path not accessible
+      LOG(ERROR) << "Could not access path \"" << path
+                 << "\" for loading CA certs. Please check permissions!";
+    }
   }
-#endif  // !defined(EWK_BRINGUP)
 }
 
 void BrowserContextEfl::InitVisitedLinkWriter() {
index 47668bc..abfdb2e 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef BROWSER_CONTEXT_EFL
 #define BROWSER_CONTEXT_EFL
 
+#include <string>
 #include <vector>
 
 #include "base/files/scoped_temp_dir.h"
@@ -130,13 +131,18 @@ class BrowserContextEfl : public BrowserContext,
   const GeolocationPermissionContextEfl& GetGeolocationPermissionContext()
       const;
 
-  void SetCertificate(const char* certificate_file);
   EWebContext* WebContext() const { return web_context_; }
 
+  void SetCertificatePath(const std::string& certificate_path);
+  const std::string& GetCertificatePath() const { return certificate_path_; }
+
   void CreateNetworkDelegate();
 
  private:
-  static void ReadCertificateAndAdd(base::FilePath* file_path);
+  // certificate_path should be either be a directory with CA certs, a CA cert
+  // file or a colon-separated list of those. CA cert files should have *.crt
+  // extension. Directories are traversed recursively.
+  static void ReadCertificateAndAdd(const std::string* certificate_path);
   SSLHostStateDelegate* GetSSLHostStateDelegate() override;
   PermissionControllerDelegate* GetPermissionControllerDelegate() override;
   mutable std::unique_ptr<GeolocationPermissionContextEfl>
@@ -154,6 +160,7 @@ class BrowserContextEfl : public BrowserContext,
   std::unique_ptr<BackgroundSyncController> background_sync_controller_;
   std::unique_ptr<PermissionControllerDelegate> permission_controller_delegate_;
   scoped_refptr<SpecialStoragePolicyEfl> special_storage_policy_efl_;
+  std::string certificate_path_;
 };
 }
 
index 00ab5fa..d6d40a0 100644 (file)
@@ -339,19 +339,13 @@ void ContentBrowserClientEfl::AllowCertificateError(
   DCHECK(web_contents);
   WebContentsDelegate* delegate = web_contents->GetDelegate();
   if (!delegate) {
-#if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
-    // FIXME: EWK_BRINGUP definition should be removed.
-    callback.Run(NULL);
-#endif  // !defined(EWK_BRINGUP)
+    std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
     return;
   }
-#if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
-  // FIXME: EWK_BRINGUP definition should be removed.
   static_cast<content::WebContentsDelegateEfl*>(delegate)
       ->RequestCertificateConfirm(web_contents, cert_error, ssl_info,
-                                  request_url, overridable, strict_enforcement,
-                                  std::move(callback));
-#endif  // !defined(EWK_BRINGUP)
+                                  request_url, is_main_frame_request,
+                                  strict_enforcement, std::move(callback));
 }
 
 NotificationControllerEfl* ContentBrowserClientEfl::GetNotificationController()
@@ -436,36 +430,6 @@ void ContentBrowserClientEfl::RenderProcessWillLaunch(
 #endif
 }
 
-void ContentBrowserClientEfl::SetCertificatePem(const net::SSLInfo& ssl_info,
-                                                int render_process_id,
-                                                int render_view_id) {
-  if (net::IsCertStatusError(ssl_info.cert_status))
-    return;
-
-  std::string pem_certificate;
-  if (!net::X509Certificate::GetPEMEncoded(ssl_info.cert->cert_buffer(),
-                                           &pem_certificate))
-    return;
-
-  base::ThreadPool::PostTask(
-      FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&ContentBrowserClientEfl::SetCertificatePemOnUIThread,
-                     render_process_id, render_view_id, pem_certificate));
-}
-
-void ContentBrowserClientEfl::SetCertificatePemOnUIThread(
-    int render_process_id,
-    int render_view_id,
-    std::string certificate) {
-  WebContents* web_contents =
-      WebContentsFromViewID(render_process_id, render_view_id);
-  if (!web_contents)
-    return;
-
-  EWebView* wv = WebViewFromWebContents(web_contents);
-  wv->SetCertificatePem(certificate);
-}
-
 content::DevToolsManagerDelegate*
 ContentBrowserClientEfl::GetDevToolsManagerDelegate() {
   return new DevToolsManagerDelegateEfl();
index 3482caa..1d23e7f 100644 (file)
@@ -108,9 +108,6 @@ class ContentBrowserClientEfl : public ContentBrowserClient {
   void OverrideWebkitPrefs(WebContents* web_contents,
                            blink::web_pref::WebPreferences* prefs);
   void RenderProcessWillLaunch(RenderProcessHost* host) override;
-  void SetCertificatePem(const net::SSLInfo& ssl_info,
-                         int render_process_id,
-                         int render_view_id);
   DevToolsManagerDelegate* GetDevToolsManagerDelegate();
   std::string GetApplicationLocale() override;
   std::unique_ptr<WebContentsViewDelegate> GetWebContentsViewDelegate(
@@ -169,9 +166,6 @@ class ContentBrowserClientEfl : public ContentBrowserClient {
       network::mojom::URLLoaderFactoryOverridePtr* factory_override) override;
   scoped_refptr<network::SharedURLLoaderFactory>
   GetSystemSharedURLLoaderFactory() override;
-  static void SetCertificatePemOnUIThread(int render_process_id,
-                                          int render_view_id,
-                                          std::string certificate);
 
   BrowserMainPartsEfl* browser_main_parts_efl_ = nullptr;
   std::unique_ptr<content::BrowserContext> browser_context_;
index 6c33ec4..7b96734 100644 (file)
@@ -457,8 +457,12 @@ bool EWebContext::GetNetworkCacheEnable() const {
 #endif
 }
 
-void EWebContext::SetCertificate(const char* certificate_file) {
-  browser_context_->SetCertificate(certificate_file);
+void EWebContext::SetCertificatePath(const std::string& certificate_path) {
+  browser_context_->SetCertificatePath(certificate_path);
+}
+
+const std::string& EWebContext::GetCertificatePath() const {
+  return browser_context_->GetCertificatePath();
 }
 
 void EWebContext::NotifyLowMemory() {
index b43a6fb..c7700a2 100644 (file)
@@ -89,7 +89,8 @@ class EWebContext {
 
   void ClearNetworkCache();
   void ClearWebkitCache();
-  void SetCertificate(const char* certificate_file);
+  void SetCertificatePath(const std::string& certificate_path);
+  const std::string& GetCertificatePath() const;
 
   void SetCacheModel(Ewk_Cache_Model);
   Ewk_Cache_Model GetCacheModel() const;
index 9dbc816..b7b1f6a 100644 (file)
@@ -2083,12 +2083,6 @@ void EWebView::SetBrowserFont() {
 #endif
 }
 
-void EWebView::SetCertificatePem(const std::string& certificate) {
-  pem_certificate_ = certificate;
-  SmartCallback<EWebViewCallbacks::SetCertificatePem>().call(
-      pem_certificate_.c_str());
-}
-
 bool EWebView::IsDragging() const {
   return wcva()->wcva_helper()->IsDragging();
 }
index 53a930f..5f12841 100755 (executable)
@@ -461,7 +461,6 @@ class EWebView {
   void ShowFileChooser(content::RenderFrameHost* render_frame_host,
                        const blink::mojom::FileChooserParams&);
   void SetBrowserFont();
-  void SetCertificatePem(const std::string& certificate);
   bool IsDragging() const;
 
   void RequestColorPicker(int r, int g, int b, int a);
@@ -629,7 +628,6 @@ class EWebView {
   gfx::Size contents_size_;
   double progress_;
   mutable std::string title_;
-  mutable std::string pem_certificate_;
   Hit_Test_Params hit_test_params_;
   base::WaitableEvent hit_test_completion_;
   double page_scale_factor_;
index 83677eb..16bcd36 100644 (file)
 #include <Eina.h>
 
 #include "eweb_view.h"
+#include "private/ewk_auth_challenge_private.h"
+#include "private/ewk_certificate_info_private.h"
+#include "private/ewk_certificate_private.h"
 #include "private/ewk_console_message_private.h"
-#include "private/ewk_error_private.h"
 #include "private/ewk_context_menu_private.h"
 #include "private/ewk_custom_handlers_private.h"
-#include "private/ewk_auth_challenge_private.h"
-#include "private/ewk_text_style_private.h"
+#include "private/ewk_error_private.h"
 #include "private/ewk_geolocation_private.h"
-#include "private/ewk_certificate_private.h"
 #include "private/ewk_policy_decision_private.h"
+#include "private/ewk_text_style_private.h"
 #include "private/ewk_user_media_private.h"
 
 typedef struct EwkObject Ewk_Auth_Request;
@@ -99,7 +100,7 @@ enum CallbackType {
   GeoLocationPermissionRequest,
   GeoLocationValid,
   RequestCertificateConfirm,
-  SetCertificatePem,
+  SSLCertificateChanged,
   PolicyResponseDecide,
   ContextMenuCustomize,
   ContextMenuItemSelected,
@@ -241,7 +242,7 @@ DECLARE_EWK_VIEW_CALLBACK(LoadCommitted, "load,committed", void);
 DECLARE_EWK_VIEW_CALLBACK(GeoLocationPermissionRequest, "geolocation,permission,request", _Ewk_Geolocation_Permission_Request*);
 DECLARE_EWK_VIEW_CALLBACK(GeoLocationValid, "geolocation,valid", Eina_Bool*);
 DECLARE_EWK_VIEW_CALLBACK(RequestCertificateConfirm, "request,certificate,confirm", _Ewk_Certificate_Policy_Decision*);
-DECLARE_EWK_VIEW_CALLBACK(SetCertificatePem, "certificate,pem,set", const char*);
+DECLARE_EWK_VIEW_CALLBACK(SSLCertificateChanged, "ssl,certificate,changed", _Ewk_Certificate_Info*);
 DECLARE_EWK_VIEW_CALLBACK(PolicyResponseDecide, "policy,response,decide", _Ewk_Policy_Decision*);
 DECLARE_EWK_VIEW_CALLBACK(ContextMenuCustomize, "contextmenu,customize", _Ewk_Context_Menu*);
 DECLARE_EWK_VIEW_CALLBACK(ContextMenuItemSelected, "contextmenu,selected", _Ewk_Context_Menu_Item*);
diff --git a/tizen_src/ewk/efl_integration/private/ewk_certificate_info_private.h b/tizen_src/ewk/efl_integration/private/ewk_certificate_info_private.h
new file mode 100644 (file)
index 0000000..8209243
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2021 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ewk_certificate_info_private_h
+#define ewk_certificate_info_private_h
+
+struct _Ewk_Certificate_Info {
+  const char* pem;
+  bool is_context_secure;
+
+  _Ewk_Certificate_Info(const char* p, bool is_secure)
+      : pem(p), is_context_secure(is_secure) {}
+  ~_Ewk_Certificate_Info() {}
+};
+
+#endif /* ewk_certificate_info_private_h */
diff --git a/tizen_src/ewk/efl_integration/private/ewk_certificate_private.cc b/tizen_src/ewk/efl_integration/private/ewk_certificate_private.cc
new file mode 100644 (file)
index 0000000..9bfa5da
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2021 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ewk_certificate_private.h"
+
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
+
+_Ewk_Certificate_Policy_Decision::_Ewk_Certificate_Policy_Decision(
+    const GURL& url,
+    const std::string& cert,
+    bool is_from_main_frame,
+    int error_code,
+    base::OnceCallback<void(content::CertificateRequestResultType)>
+        result_callback)
+    : is_from_main_frame_(is_from_main_frame),
+      error_(error_code),
+      callback_(std::move(result_callback)) {
+  is_decided_ = false;
+  is_suspended_ = false;
+  url_ = eina_stringshare_add(url.spec().c_str());
+  certificate_pem_ = eina_stringshare_add(cert.c_str());
+}
+
+_Ewk_Certificate_Policy_Decision::~_Ewk_Certificate_Policy_Decision() {
+  eina_stringshare_del(url_);
+  eina_stringshare_del(certificate_pem_);
+}
+
+bool _Ewk_Certificate_Policy_Decision::SetDecision(bool allowed) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (!is_decided_) {
+    is_decided_ = true;
+
+    if (!callback_.is_null()) {
+      std::move(callback_).Run(
+          allowed ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
+                  : content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
+    }
+
+    if (is_suspended_) {
+      // If decision was suspended, then it was not deleted by the creator
+      // Deletion of this object must be done after decision was made, as
+      // this object will no longer be valid. But if decision was not suspended
+      // it will be deleted right after permission callbacks are executed.
+      BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
+    }
+    return true;
+  }
+  return false;
+}
+
+void _Ewk_Certificate_Policy_Decision::Ignore() {
+  is_decided_ = true;
+}
+
+bool _Ewk_Certificate_Policy_Decision::Suspend() {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (!is_decided_) {
+    is_suspended_ = true;
+    return true;
+  }
+  return false;
+}
index 1fdc5d6..02ae165 100644 (file)
@@ -1,48 +1,53 @@
-// Copyright 2014 Samsung Electronics. All rights reserved.
+// Copyright 2021 Samsung Electronics. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef EWK_CERTIFICATE_PRIVATE_H_
 #define EWK_CERTIFICATE_PRIVATE_H_
 
+#include <Eina.h>
 #include <string>
 
 #include "base/callback.h"
-#include "ewk_suspendable_object.h"
+#include "content/public/browser/certificate_request_result_type.h"
 #include "url/gurl.h"
 
-class _Ewk_Certificate_Policy_Decision : public Ewk_Suspendable_Object {
+struct _Ewk_Certificate_Policy_Decision {
  public:
   _Ewk_Certificate_Policy_Decision(
       const GURL& url,
       const std::string& cert,
+      bool is_from_main_frame,
       int error_code,
-      base::OnceCallback<void(bool)> result_callback)
-      : url_(NULL),
-        certificatePem_(NULL),
-        error_(error_code),
-        callback_(std::move(result_callback)) {
-    url_ = eina_stringshare_add(url.spec().c_str());
-    certificatePem_ = eina_stringshare_add(cert.c_str());
+      base::OnceCallback<void(content::CertificateRequestResultType)>
+          result_callback);
+  ~_Ewk_Certificate_Policy_Decision();
+
+  bool SetDecision(bool allowed);
+  void Ignore();
+  bool Suspend();
+  bool IsDecided() const { return is_decided_; }
+  bool IsSuspended() const { return is_suspended_; }
+
+  Eina_Stringshare* Url() const { return url_; }
+  Eina_Stringshare* CertificatePem() const { return certificate_pem_; }
+  bool IsFromMainFrame() const { return is_from_main_frame_; }
+  int Error() const { return error_; }
+  base::OnceCallback<void(content::CertificateRequestResultType)>& Callback() {
+    return callback_;
   }
 
-  ~_Ewk_Certificate_Policy_Decision() {
-    eina_stringshare_del(url_);
-    eina_stringshare_del(certificatePem_);
-  }
-
-  Eina_Stringshare* url() const { return url_; }
-  Eina_Stringshare* certificatePem() const { return certificatePem_; }
-  int error() const { return error_; }
-
  private:
-  void runCallback(bool allowed) override { std::move(callback_).Run(allowed); }
+  bool is_decided_;
+  bool is_suspended_;
 
-  Eina_Stringshare* url_;
-  Eina_Stringshare* certificatePem_;
+  Eina_Stringshare* url_ = nullptr;
+  Eina_Stringshare* certificate_pem_ = nullptr;
+  bool is_from_main_frame_;
   int error_;
 
-  base::OnceCallback<void(bool)> callback_;  // run when policy is set by app
+  // run when policy is set by app
+  base::OnceCallback<void(content::CertificateRequestResultType)> callback_;
 };
 
 #endif /* EWK_CERTIFICATE_PRIVATE_H_ */
index 922eb92..ef02ab9 100644 (file)
@@ -92,8 +92,12 @@ void Ewk_Context::SetDidStartDownloadCallback(Ewk_Context_Did_Start_Download_Cal
   impl->SetDidStartDownloadCallback(callback, user_data);
 }
 
-void Ewk_Context::SetCertificate(const char* certificate_file) {
-  impl->SetCertificate(certificate_file);
+void Ewk_Context::SetCertificatePath(const char* certificate_path) {
+  impl->SetCertificatePath(certificate_path);
+}
+
+const char* Ewk_Context::GetCertificatePath() const {
+  return impl->GetCertificatePath().c_str();
 }
 
 void Ewk_Context::SetProxyUri(const char* uri) {
index ee969bf..811d426 100644 (file)
@@ -41,7 +41,8 @@ struct Ewk_Context : public base::RefCounted<Ewk_Context> {
   //EwkDidStartDownloadCallback* DidStartDownloadCallback();
 
   // Certificate
-  void SetCertificate(const char* certificate_file);
+  void SetCertificatePath(const char* certificate_path);
+  const char* GetCertificatePath() const;
 
   // Proxy URI
   void SetProxyUri(const char* uri);
index bcb58f3..2f79ad0 100644 (file)
 
 #include <string>
 
+#include "net/cert/cert_status_flags.h"
+#include "private/ewk_certificate_info_private.h"
 #include "private/ewk_certificate_private.h"
 #include "private/ewk_private.h"
 
 void ewk_certificate_policy_decision_allowed_set(Ewk_Certificate_Policy_Decision* certificatePolicyDecision, Eina_Bool allowed)
 {
   EINA_SAFETY_ON_NULL_RETURN(certificatePolicyDecision);
-  certificatePolicyDecision->setDecision(allowed == EINA_TRUE);
+  certificatePolicyDecision->SetDecision(allowed == EINA_TRUE);
 }
 
 Eina_Bool ewk_certificate_policy_decision_suspend(Ewk_Certificate_Policy_Decision* certificatePolicyDecision)
 {
   EINA_SAFETY_ON_NULL_RETURN_VAL(certificatePolicyDecision, EINA_FALSE);
-  return certificatePolicyDecision->suspend();
+  return certificatePolicyDecision->Suspend();
 }
 
 Eina_Stringshare* ewk_certificate_policy_decision_url_get(Ewk_Certificate_Policy_Decision* certificatePolicyDecision)
 {
   EINA_SAFETY_ON_NULL_RETURN_VAL(certificatePolicyDecision, "");
-  return certificatePolicyDecision->url();
+  return certificatePolicyDecision->Url();
 }
 
 Eina_Stringshare* ewk_certificate_policy_decision_certificate_pem_get(Ewk_Certificate_Policy_Decision* certificatePolicyDecision)
 {
   EINA_SAFETY_ON_NULL_RETURN_VAL(certificatePolicyDecision, "");
-  return certificatePolicyDecision->certificatePem();
+  return certificatePolicyDecision->CertificatePem();
 }
 
-Ewk_Certificate_Policy_Decision_Error ewk_certificate_policy_decision_error_get(Ewk_Certificate_Policy_Decision* certificate_policy_decision)
-{
-  LOG_EWK_API_MOCKUP();
-  return EWK_CERTIFICATE_POLICY_DECISION_ERROR_UNKNOWN;
+Ewk_Certificate_Policy_Decision_Error ewk_certificate_policy_decision_error_get(
+    Ewk_Certificate_Policy_Decision* certificatePolicyDecision) {
+  EINA_SAFETY_ON_NULL_RETURN_VAL(certificatePolicyDecision,
+                                 EWK_CERTIFICATE_POLICY_DECISION_ERROR_UNKNOWN);
+  net::CertStatus cert_status =
+      net::MapNetErrorToCertStatus(certificatePolicyDecision->Error());
+  switch (cert_status) {
+    case net::CERT_STATUS_COMMON_NAME_INVALID:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_COMMON_NAME_INVALID;
+    case net::CERT_STATUS_DATE_INVALID:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_DATE_INVALID;
+    case net::CERT_STATUS_AUTHORITY_INVALID:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_AUTHORITY_INVALID;
+    case net::CERT_STATUS_NO_REVOCATION_MECHANISM:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_NO_REVOCATION_MECHANISM;
+    case net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_UNABLE_TO_CHECK_REVOCATION;
+    case net::CERT_STATUS_REVOKED:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_REVOKED;
+    case net::CERT_STATUS_INVALID:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_INVALID;
+    case net::CERT_STATUS_WEAK_SIGNATURE_ALGORITHM:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_WEAK_ALGORITHM;
+    case net::CERT_STATUS_NON_UNIQUE_NAME:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_NON_UNIQUE_NAME;
+    case net::CERT_STATUS_WEAK_KEY:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_WEAK_KEY;
+    case net::CERT_STATUS_PINNED_KEY_MISSING:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_PINNED_KEY_NOT_IN_CHAIN;
+    case net::CERT_STATUS_NAME_CONSTRAINT_VIOLATION:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_NAME_VIOLATION;
+    case net::CERT_STATUS_VALIDITY_TOO_LONG:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_VALIDITY_TOO_LONG;
+    default:
+      return EWK_CERTIFICATE_POLICY_DECISION_ERROR_UNKNOWN;
+  }
 }
 
 const char* ewk_certificate_info_pem_get(const Ewk_Certificate_Info* cert_info)
 {
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  EINA_SAFETY_ON_NULL_RETURN_VAL(cert_info, nullptr);
+  return cert_info->pem;
 }
 
 Eina_Bool ewk_certificate_info_is_context_secure(const Ewk_Certificate_Info* cert_info)
 {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EINA_SAFETY_ON_NULL_RETURN_VAL(cert_info, EINA_FALSE);
+  return cert_info->is_context_secure;
 }
 Eina_Bool ewk_certificate_policy_decision_from_main_frame_get(const Ewk_Certificate_Policy_Decision* certificate_policy_decision)
 {
-  LOG_EWK_API_MOCKUP();
-  return false;
+  EINA_SAFETY_ON_NULL_RETURN_VAL(certificate_policy_decision, EINA_FALSE);
+  return certificate_policy_decision->IsFromMainFrame();
 }
index 98b2472..8f1b688 100644 (file)
@@ -337,23 +337,18 @@ Eina_Bool ewk_context_cache_disabled_get(Ewk_Context* context)
   return !context->GetNetworkCacheEnable();
 }
 
-Eina_Bool ewk_context_certificate_file_set(Ewk_Context *context, const char *certificate_file)
-{
+Eina_Bool ewk_context_certificate_file_set(Ewk_Context* context,
+                                           const char* certificate_path) {
   EINA_SAFETY_ON_NULL_RETURN_VAL(context, EINA_FALSE);
-  EINA_SAFETY_ON_NULL_RETURN_VAL(certificate_file, EINA_FALSE);
-  context->SetCertificate(certificate_file);
+  EINA_SAFETY_ON_NULL_RETURN_VAL(certificate_path, EINA_FALSE);
+  context->SetCertificatePath(certificate_path);
   return true;
 }
 
 const char* ewk_context_certificate_file_get(const Ewk_Context* context)
 {
   EINA_SAFETY_ON_NULL_RETURN_VAL(context, NULL);
-#if !defined(EWK_BRINGUP)
-  return context->GetCertificate();
-#else
-  LOG_EWK_API_MOCKUP();
-  return NULL;
-#endif
+  return context->GetCertificatePath();
 }
 
 Eina_Bool ewk_context_cache_clear(Ewk_Context* context)
index 16b6108..3cf1919 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "web_contents_delegate_efl.h"
 
+#include <tuple>
+
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/ttrace.h"
 #include "browser/input_picker/color_chooser_efl.h"
@@ -26,6 +28,7 @@
 #include "eweb_view.h"
 #include "eweb_view_callbacks.h"
 #include "net/base/load_states.h"
+#include "net/cert/x509_certificate.h"
 #include "net/http/http_response_headers.h"
 #include "private/ewk_certificate_private.h"
 #include "private/ewk_console_message_private.h"
@@ -345,33 +348,78 @@ void WebContentsDelegateEfl::RequestCertificateConfirm(
     int cert_error,
     const net::SSLInfo& ssl_info,
     const GURL& url,
-    bool /*overridable*/,
+    bool is_main_frame_request,
     bool /*strict_enforcement*/,
     base::OnceCallback<void(CertificateRequestResultType)> callback) {
-#if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
-  // FIXME: EWK_BRINGUP definition should be removed.
-  DCHECK(result);
   std::string pem_certificate;
-  if (!net::X509Certificate::GetPEMEncoded(ssl_info.cert->os_cert_handle(),
+  if (!net::X509Certificate::GetPEMEncoded(ssl_info.cert->cert_buffer(),
                                            &pem_certificate)) {
-    *result = CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
+    LOG(INFO) << "Certificate for URL: " << url.spec()
+              << " could not be opened";
+    std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
     return;
   }
   certificate_policy_decision_.reset(new _Ewk_Certificate_Policy_Decision(
-      url, pem_certificate, cert_error, std::move(callback)));
-#endif  // !defined(EWK_BRINGUP)
+      url, pem_certificate, is_main_frame_request, cert_error,
+      std::move(callback)));
+
   web_view_->SmartCallback<EWebViewCallbacks::RequestCertificateConfirm>().call(
       certificate_policy_decision_.get());
+  LOG(INFO) << "Certificate policy decision called for URL: " << url.spec()
+            << " with cert_error: " << cert_error;
 
   // if policy is suspended, the API takes over the policy object lifetime
   // and policy will be deleted after decision is made
-#if !defined(EWK_BRINGUP)  // FIXME: m108 bringup
-  if (certificate_policy_decision_->isSuspended()) {
-    ignore_result(certificate_policy_decision_.release());
+  if (certificate_policy_decision_->IsSuspended()) {
+    std::ignore = certificate_policy_decision_.release();
+  } else if (!certificate_policy_decision_->IsDecided()) {
+    // When the embeder neither suspended certificate decision nor handled it
+    // inside the smart callback by calling
+    // ewk_certificate_policy_decision_allowed_set
+    // this means the embeder let chromium decide what to do.
+    if (!is_main_frame_request) {
+      // A sub-resource has a certificate error. The user doesn't really
+      // have a context for making the right decision, so block the
+      // request hard.
+      std::move(certificate_policy_decision_->Callback())
+          .Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
+    } else {
+      // By default chromium-efl allows page to be opened with certificate
+      // compromise.
+      certificate_policy_decision_->SetDecision(true);
+      LOG(WARNING) << "Certificate for " << url.spec() << " was compromised";
+    }
+  }
+}
+
+void WebContentsDelegateEfl::VisibleSecurityStateChanged(WebContents* source) {
+  std::unique_ptr<_Ewk_Certificate_Info> certificate_info;
+  std::string pem_certificate;
+  SSLStatus ssl_status = source->GetController().GetVisibleEntry()->GetSSL();
+  scoped_refptr<net::X509Certificate> cert = ssl_status.certificate;
+
+  if (!cert) {
+    LOG(ERROR) << "Unable to get certificate!";
+    certificate_info.reset(new _Ewk_Certificate_Info(nullptr, false));
   } else {
-    certificate_policy_decision_->setDecision(true);
+    if (!net::X509Certificate::GetPEMEncoded(cert->cert_buffer(),
+                                             &pem_certificate)) {
+      LOG(ERROR) << "Unable to get encoded PEM!";
+      return;
+    }
+    // Note: The implementation below is a copy of the one in
+    // ChromeAutofillClient::IsContextSecure, and should be kept in sync
+    // until crbug.com/505388 gets implemented.
+    bool is_context_secure =
+        ssl_status.certificate &&
+        !net::IsCertStatusError(ssl_status.cert_status) &&
+        !(ssl_status.content_status & content::SSLStatus::RAN_INSECURE_CONTENT);
+
+    certificate_info.reset(
+        new _Ewk_Certificate_Info(pem_certificate.c_str(), is_context_secure));
   }
-#endif
+  web_view_->SmartCallback<EWebViewCallbacks::SSLCertificateChanged>().call(
+      certificate_info.get());
 }
 
 void WebContentsDelegateEfl::ActivateContents(WebContents* contents) {
index dcb7068..1919bfe 100644 (file)
@@ -78,7 +78,7 @@ class WebContentsDelegateEfl : public WebContentsDelegate {
       int cert_error,
       const net::SSLInfo& ssl_info,
       const GURL& url,
-      bool overridable,
+      bool is_main_frame_request,
       bool strict_enforcement,
       base::OnceCallback<void(CertificateRequestResultType)> callback);
 
@@ -114,6 +114,7 @@ class WebContentsDelegateEfl : public WebContentsDelegate {
 #endif
   bool PreHandleGestureEvent(WebContents* source,
                              const blink::WebGestureEvent& event) override;
+  void VisibleSecurityStateChanged(WebContents* source) override;
   EWebView* web_view() const { return web_view_; }
   WebContents& web_contents() const { return web_contents_; }
 
index 0cd7971..46d7b39 100644 (file)
@@ -100,6 +100,8 @@ test("ewk_unittests") {
     "utc_blink_ewk_base.h",
     "utc_blink_ewk_certificate_policy_decision_allowed_set_func.cpp",
     "utc_blink_ewk_certificate_policy_decision_certificate_pem_get_func.cpp",
+    "utc_blink_ewk_certificate_policy_decision_error_get_func.cpp",
+    "utc_blink_ewk_certificate_policy_decision_from_main_frame_get_func.cpp",
     "utc_blink_ewk_certificate_policy_decision_suspend_func.cpp",
     "utc_blink_ewk_certificate_policy_decision_url_get_func.cpp",
     "utc_blink_ewk_console_message_level_get_func.cpp",
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_certificate_policy_decision_error_get_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_certificate_policy_decision_error_get_func.cpp
new file mode 100644 (file)
index 0000000..b7ed5db
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright 2021 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "utc_blink_ewk_base.h"
+
+static const char* const kUrlWithCertCompromise =
+    "https://www.pcwebshop.co.uk/";
+
+class utc_blink_ewk_certificate_policy_decision_error_get
+    : public utc_blink_ewk_base {
+ protected:
+  utc_blink_ewk_certificate_policy_decision_error_get()
+      : error_(EWK_CERTIFICATE_POLICY_DECISION_ERROR_UNKNOWN) {}
+
+  void PostSetUp() override {
+    evas_object_smart_callback_add(GetEwkWebView(),
+                                   "request,certificate,confirm",
+                                   request_certificate_confirm, this);
+  }
+
+  void PreTearDown() override {
+    evas_object_smart_callback_del(GetEwkWebView(),
+                                   "request,certificate,confirm",
+                                   request_certificate_confirm);
+  }
+
+  void LoadFinished(Evas_Object* webview) override { EventLoopStop(Failure); }
+
+  static void request_certificate_confirm(void* data,
+                                          Evas_Object* webview,
+                                          void* event_info) {
+    auto owner =
+        static_cast<utc_blink_ewk_certificate_policy_decision_error_get*>(data);
+
+    owner->error_ = ewk_certificate_policy_decision_error_get(
+        static_cast<Ewk_Certificate_Policy_Decision*>(event_info));
+
+    owner->EventLoopStop(Success);
+  }
+
+  Ewk_Certificate_Policy_Decision_Error error_;
+};
+
+/**
+ * @brief Checking whether ewk_certificate_policy_decision_error_get
+ *        returns know error code.
+ */
+TEST_F(utc_blink_ewk_certificate_policy_decision_error_get, POS_TEST) {
+  ASSERT_EQ(EINA_TRUE,
+            ewk_view_url_set(GetEwkWebView(), kUrlWithCertCompromise));
+  ASSERT_EQ(Success, EventLoopStart());
+  ASSERT_NE(EWK_CERTIFICATE_POLICY_DECISION_ERROR_UNKNOWN, error_);
+}
+
+/**
+ * @brief Checking whether function works properly in case of NULL argument.
+ */
+TEST_F(utc_blink_ewk_certificate_policy_decision_error_get,
+       NEG_TEST_INVALID_PARAM) {
+  ASSERT_EQ(EWK_CERTIFICATE_POLICY_DECISION_ERROR_UNKNOWN,
+            ewk_certificate_policy_decision_error_get(nullptr));
+}
diff --git a/tizen_src/ewk/unittest/utc_blink_ewk_certificate_policy_decision_from_main_frame_get_func.cpp b/tizen_src/ewk/unittest/utc_blink_ewk_certificate_policy_decision_from_main_frame_get_func.cpp
new file mode 100644 (file)
index 0000000..87659de
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright 2021 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "utc_blink_ewk_base.h"
+
+static const char* const kUrlWithCertCompromiseOnMainFrame =
+    "https://www.pcwebshop.co.uk/";
+
+static const char* const kUrlWithCertCompromiseOnSubResource =
+    "https://projects.dm.id.lv/Public-Key-Pins_test";
+
+class utc_blink_ewk_certificate_policy_decision_from_main_frame_get
+    : public utc_blink_ewk_base {
+ protected:
+  utc_blink_ewk_certificate_policy_decision_from_main_frame_get()
+      : is_main_frame_(false) {}
+
+  void PostSetUp() override {
+    evas_object_smart_callback_add(GetEwkWebView(),
+                                   "request,certificate,confirm",
+                                   request_certificate_confirm, this);
+  }
+
+  void PreTearDown() override {
+    evas_object_smart_callback_del(GetEwkWebView(),
+                                   "request,certificate,confirm",
+                                   request_certificate_confirm);
+  }
+
+  void LoadFinished(Evas_Object* webview) override { EventLoopStop(Failure); }
+
+  static void request_certificate_confirm(void* data,
+                                          Evas_Object* webview,
+                                          void* event_info) {
+    auto owner = static_cast<
+        utc_blink_ewk_certificate_policy_decision_from_main_frame_get*>(data);
+
+    owner->is_main_frame_ = ewk_certificate_policy_decision_from_main_frame_get(
+        static_cast<Ewk_Certificate_Policy_Decision*>(event_info));
+
+    owner->EventLoopStop(Success);
+  }
+
+  Eina_Bool is_main_frame_;
+};
+
+/**
+ * @brief Checking whether ewk_certificate_policy_decision_from_main_frame_get
+ *        returns EINA_TRUE if certificate compromise comes from main frame.
+ */
+TEST_F(utc_blink_ewk_certificate_policy_decision_from_main_frame_get,
+       POS_TEST_CERT_ISSUE_FROM_MAIN_FRAME) {
+  ASSERT_EQ(EINA_TRUE, ewk_view_url_set(GetEwkWebView(),
+                                        kUrlWithCertCompromiseOnMainFrame));
+  ASSERT_EQ(Success, EventLoopStart());
+  ASSERT_EQ(EINA_TRUE, is_main_frame_);
+}
+
+/**
+ * @brief Checking whether ewk_certificate_policy_decision_from_main_frame_get
+ *        returns EINA_FALSE if certificate compromise comes from sub resource.
+ */
+TEST_F(utc_blink_ewk_certificate_policy_decision_from_main_frame_get,
+       POS_TEST_CERT_ISSUE_FROM_SUBRESOURCE) {
+  ASSERT_EQ(EINA_TRUE, ewk_view_url_set(GetEwkWebView(),
+                                        kUrlWithCertCompromiseOnSubResource));
+  ASSERT_EQ(Success, EventLoopStart());
+  ASSERT_EQ(EINA_FALSE, is_main_frame_);
+}
+
+/**
+ * @brief Checking whether function works properly in case of NULL argument.
+ */
+TEST_F(utc_blink_ewk_certificate_policy_decision_from_main_frame_get,
+       NEG_TEST_INVALID_PARAM) {
+  ASSERT_EQ(EINA_FALSE,
+            ewk_certificate_policy_decision_from_main_frame_get(nullptr));
+}
index 7cda50c..6826041 100755 (executable)
@@ -6,7 +6,7 @@
 
 #include "utc_blink_ewk_base.h"
 
-#define URL "https://www.pcwebshop.co.uk"
+#define URL "https://wrong.host.badssl.com/"
 
 class utc_blink_ewk_certificate_policy_decision_suspend  : public utc_blink_ewk_base
 {