// 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);
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;
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_)));
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);
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
#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
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);
}
#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;
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.
friend class Notifier;
raw_ptr<Notifier> notifier_ = nullptr;
#endif
+
+#if BUILDFLAG(IS_EFL)
+ base::Lock lock_;
+#endif
};
} // namespace net
"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",
#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"
#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"
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 {
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() {
#ifndef BROWSER_CONTEXT_EFL
#define BROWSER_CONTEXT_EFL
+#include <string>
#include <vector>
#include "base/files/scoped_temp_dir.h"
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>
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_;
};
}
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()
#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();
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(
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_;
#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() {
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;
#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();
}
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);
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_;
#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;
GeoLocationPermissionRequest,
GeoLocationValid,
RequestCertificateConfirm,
- SetCertificatePem,
+ SSLCertificateChanged,
PolicyResponseDecide,
ContextMenuCustomize,
ContextMenuItemSelected,
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*);
--- /dev/null
+// 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 */
--- /dev/null
+// 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;
+}
-// 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_ */
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) {
//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);
#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();
}
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)
#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"
#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"
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) {
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);
#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_; }
"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",
--- /dev/null
+// 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));
+}
--- /dev/null
+// 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));
+}
#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
{