[DA] Enable Passkey for M94 91/317791/8 accepted/tizen_7.0_unified accepted/tizen/7.0/unified/20241008.173906
authorHrithik Mohan <h.puchakayal@samsung.com>
Thu, 12 Sep 2024 12:42:06 +0000 (18:12 +0530)
committerHrithik Mohan <h.puchakayal@samsung.com>
Thu, 3 Oct 2024 10:16:22 +0000 (15:46 +0530)
Enable webauthentication/passkey for M94
Ref:
1. https://review.tizen.org/gerrit/#/c/313060/
2. https://review.tizen.org/gerrit/#/c/314179/
3. https://review.tizen.org/gerrit/#/c/314684/
4. https://review.tizen.org/gerrit/#/c/314814/
5. https://review.tizen.org/gerrit/#/c/314766/

Change-Id: Iea1b9e8506ca70906af5aa5057c2db2bfe462069
Signed-off-by: Hrithik Mohan <h.puchakayal@samsung.com>
30 files changed:
content/browser/renderer_host/render_frame_host_impl.cc
content/browser/renderer_host/render_frame_host_impl.h
content/browser/renderer_host/render_widget_host_impl.cc
content/browser/renderer_host/render_widget_host_impl.h
content/browser/renderer_host/render_widget_host_view_aura.cc
content/browser/renderer_host/render_widget_host_view_aura.h
content/browser/renderer_host/render_widget_host_view_base.h
content/browser/webauth/authenticator_impl.cc
content/browser/webauth/authenticator_impl.h
content/public/browser/web_contents_delegate.h
packaging/chromium-efl.spec
tizen_src/build/BUILD.gn
tizen_src/build/config/BUILD.gn
tizen_src/build/config/tizen_features.gni
tizen_src/build/gbs.conf.in
tizen_src/chromium_impl/content/browser/browser_efl.gni
tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.cc
tizen_src/chromium_impl/content/browser/renderer_host/render_widget_host_view_efl.h
tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.h [new file with mode: 0644]
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/public/ewk_view.cc
tizen_src/ewk/efl_integration/public/ewk_view_internal.h
tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.h
tizen_src/ewk/ubrowser/BUILD.gn
tizen_src/ewk/ubrowser/window.cc
tizen_src/ewk/ubrowser/window.h

index dcdeac41bb1968f03c82c05ef4875993170a4f10..f55472c3ad2ba46e022d2aee24e169cdc35a1f38 100644 (file)
@@ -12340,4 +12340,27 @@ RenderWidgetHostView* RenderFrameHostImpl::AccessibilityGetView() {
 }
 #endif
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+void RenderFrameHostImpl::DisplayQRCode(std::string contents) {
+  if (GetLocalRenderWidgetHost()) {
+    GetLocalRenderWidgetHost()->DisplayQRCode(contents);
+  }
+}
+
+void RenderFrameHostImpl::CloseQRCode() {
+  if (GetLocalRenderWidgetHost()) {
+    GetLocalRenderWidgetHost()->CloseQRCode();
+  }
+}
+
+void RenderFrameHostImpl::set_authenticator(
+    base::WeakPtr<AuthenticatorCommonTizen> authenticator) {
+  authenticator_ = authenticator;
+}
+
+AuthenticatorCommonTizen* RenderFrameHostImpl::get_authenticator() {
+  return authenticator_.get();
+}
+#endif
+
 }  // namespace content
index e2a42271a357fd5eadd773e1808b6c35ad819e69..49070d86ef2f592124b68bd585a74188b6fa7b33 100644 (file)
 #include "content/common/pepper_plugin.mojom.h"
 #endif
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+#include "content/browser/webauthn/authenticator_common_tizen.h"
+#endif
+
 namespace blink {
 class AssociatedInterfaceRegistry;
 class DocumentPolicy;
@@ -314,6 +318,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
   RenderWidgetHostImpl* GetRenderWidgetHost() override;
   RenderWidgetHostView* GetView() override;
   RenderFrameHostImpl* GetParent() override;
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  void DisplayQRCode(std::string contents);
+  void CloseQRCode();
+  void set_authenticator(base::WeakPtr<AuthenticatorCommonTizen> authenticator);
+  AuthenticatorCommonTizen* get_authenticator();
+#endif
   RenderFrameHostImpl* GetMainFrame() override;
   PageImpl& GetPage() override;
   std::vector<RenderFrameHost*> GetFramesInSubtree() override;
@@ -3599,6 +3609,10 @@ class CONTENT_EXPORT RenderFrameHostImpl
   mojo::AssociatedReceiver<mojom::DomAutomationControllerHost>
       dom_automation_controller_receiver_{this};
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  base::WeakPtr<AuthenticatorCommonTizen> authenticator_;
+#endif
+
 #if BUILDFLAG(ENABLE_PLUGINS)
   mojo::AssociatedReceiver<mojom::PepperHost> pepper_host_receiver_{this};
   std::map<int32_t, std::unique_ptr<PepperPluginInstanceHost>>
index f043d09858ff3565b506102bcef2e364871ced0c..6f75aa30efce2123c2b252a9321c3be60c78f352 100644 (file)
@@ -562,6 +562,24 @@ RenderWidgetHostImpl::GetAllRenderWidgetHosts() {
   return std::move(hosts);
 }
 
+#if defined(USE_EFL)
+void RenderWidgetHostImpl::DisplayQRCode(std::string contents) {
+  if (!view_) {
+    LOG(ERROR) << "view_ is null";
+    return;
+  }
+  view_->DisplayQRCode(contents);
+}
+
+void RenderWidgetHostImpl::CloseQRCode() {
+  if (!view_) {
+    LOG(ERROR) << "view_ is null";
+    return;
+  }
+  view_->CloseQRCode();
+}
+#endif
+
 // static
 RenderWidgetHostImpl* RenderWidgetHostImpl::From(RenderWidgetHost* rwh) {
   return static_cast<RenderWidgetHostImpl*>(rwh);
index 1d63d7f9057704dadfd916d8f3567b667e5449d4..0ffb2dda6d88e3ffb9c9b07bf15d4629f345abff 100755 (executable)
@@ -421,6 +421,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl
   void RequestVideoPlaying(int callback_id);
   void OnGetVideoPlayingStatus(int callback_id, bool is_playing);
 
+#if defined(USE_EFL)
+  void DisplayQRCode(std::string contents);
+  void CloseQRCode();
+#endif
+
   RenderWidgetHostDelegate* delegate() const { return delegate_; }
 
   // Bind the provided widget interfaces.
index 9ea3f7da129a09ab2ce7fc2d01f3c2d5b36a74e5..d5bb115f83a5da7ad3b2d08628a3631353e368ea 100644 (file)
@@ -651,6 +651,14 @@ void RenderWidgetHostViewAura::UpdateBackgroundColor() {
   window_->layer()->SetColor(color);
 }
 
+#if defined(USE_EFL)
+void RenderWidgetHostViewAura::DisplayQRCode(std::string contents) {
+  if (efl_helper_) {
+    efl_helper_->DisplayQRCode(contents);
+  }
+}
+#endif
+
 absl::optional<DisplayFeature> RenderWidgetHostViewAura::GetDisplayFeature() {
   return display_feature_;
 }
index 03b5d09a1d30deae9a3b2a09b845616e57eec59a..50eceea10fe064bf4dfe0746d9826983fedcb4df 100644 (file)
@@ -393,6 +393,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
   void SetDisplayFeatureForTesting(
       const DisplayFeature* display_feature) override;
 
+#if defined(USE_EFL)
+  void DisplayQRCode(std::string contents) override;
+  void CloseQRCode() override;
+#endif
+
  private:
   friend class DelegatedFrameHostClientAura;
   friend class FakeRenderWidgetHostViewAura;
index 029422ae05c1c2ab304ef7a3ade2ee878371443a..f66c7ac401bff935af9bd98aa2bff5a79069b9f3 100644 (file)
@@ -637,6 +637,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
   virtual void MoveFocusToBrowser(int direction) {}
 #endif
 
+#if defined(USE_EFL)
+  virtual void DisplayQRCode(std::string contents) {}
+  virtual void CloseQRCode() {}
+#endif
+
  protected:
   explicit RenderWidgetHostViewBase(RenderWidgetHost* host);
   ~RenderWidgetHostViewBase() override;
index 512bf2bdb645b0f0e139fe8e7f76cf7358aad1f3..7bc493be5cdca32c769dd8bc3fe27456ccacb6c3 100644 (file)
@@ -9,7 +9,11 @@
 #include <utility>
 
 #include "base/timer/timer.h"
+#if defined(TIZEN_PASSKEY_SUPPORT)
+#include "content/browser/webauthn/authenticator_common_tizen.h"
+#else
 #include "content/browser/webauth/authenticator_common.h"
+#endif
 #include "content/public/browser/document_service_base.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
@@ -30,11 +34,27 @@ void AuthenticatorImpl::Create(
   // AuthenticatorImpl owns itself. It self-destructs when the RenderFrameHost
   // navigates or is deleted. See DocumentServiceBase for details.
   DCHECK(render_frame_host);
+#if defined(TIZEN_PASSKEY_SUPPORT)
   new AuthenticatorImpl(
+      render_frame_host, std::move(receiver),
+      std::make_unique<AuthenticatorCommonTizen>(render_frame_host));
+#else
+ new AuthenticatorImpl(
       render_frame_host, std::move(receiver),
       std::make_unique<AuthenticatorCommon>(render_frame_host));
+#endif
 }
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+AuthenticatorImpl::AuthenticatorImpl(
+    RenderFrameHost* render_frame_host,
+    mojo::PendingReceiver<blink::mojom::Authenticator> receiver,
+    std::unique_ptr<AuthenticatorCommonTizen> authenticator_common_tizen)
+    : DocumentServiceBase(render_frame_host, std::move(receiver)),
+      authenticator_common_tizen_(std::move(authenticator_common_tizen)) {
+  DCHECK(authenticator_common_tizen_);
+}
+#else
 AuthenticatorImpl::AuthenticatorImpl(
     RenderFrameHost* render_frame_host,
     mojo::PendingReceiver<blink::mojom::Authenticator> receiver,
@@ -43,9 +63,38 @@ AuthenticatorImpl::AuthenticatorImpl(
       authenticator_common_(std::move(authenticator_common)) {
   DCHECK(authenticator_common_);
 }
+#endif //defined(TIZEN_PASSKEY_SUPPORT)
 
 AuthenticatorImpl::~AuthenticatorImpl() = default;
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+// mojom::Authenticator
+void AuthenticatorImpl::MakeCredential(
+    blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
+    MakeCredentialCallback callback) {
+  authenticator_common_tizen_->MakeCredential(origin(), std::move(options),
+                                             std::move(callback));
+}
+
+// mojom::Authenticator
+void AuthenticatorImpl::GetAssertion(
+    blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
+    GetAssertionCallback callback) {
+  authenticator_common_tizen_->GetAssertion(origin(), std::move(options),
+                                           /*payment=*/nullptr,
+                                           std::move(callback));
+}
+
+void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
+    IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) {
+  authenticator_common_tizen_->IsUserVerifyingPlatformAuthenticatorAvailable(
+      std::move(callback));
+}
+
+void AuthenticatorImpl::Cancel() {
+  authenticator_common_tizen_->Cancel();
+}
+#else
 // mojom::Authenticator
 void AuthenticatorImpl::MakeCredential(
     blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
@@ -71,5 +120,6 @@ void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
 void AuthenticatorImpl::Cancel() {
   authenticator_common_->Cancel();
 }
+#endif //defined(TIZEN_PASSKEY_SUPPORT)
 
 }  // namespace content
index d5d0fecad150aee9fdef16d102aeb13e6c2c8f63..9ef6be32f9214a2b5ef594732f204b61d56628dd 100644 (file)
@@ -36,7 +36,12 @@ class Origin;
 
 namespace content {
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+class AuthenticatorCommonTizen;
+#else
 class AuthenticatorCommon;
+#endif
+
 class RenderFrameHost;
 
 // Implementation of the public Authenticator interface.
@@ -51,14 +56,27 @@ class CONTENT_EXPORT AuthenticatorImpl
   friend class AuthenticatorImplTest;
   friend class AuthenticatorImplRequestDelegateTest;
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  AuthenticatorImpl(RenderFrameHost* render_frame_host,
+                    mojo::PendingReceiver<blink::mojom::Authenticator> receiver,
+                    std::unique_ptr<AuthenticatorCommonTizen> authenticator_common_tizen);
+#else
   AuthenticatorImpl(RenderFrameHost* render_frame_host,
                     mojo::PendingReceiver<blink::mojom::Authenticator> receiver,
                     std::unique_ptr<AuthenticatorCommon> authenticator_common);
+#endif
+
   ~AuthenticatorImpl() override;
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  AuthenticatorCommonTizen* get_authenticator_common_for_testing() {
+    return authenticator_common_tizen_.get();
+  }
+#else
   AuthenticatorCommon* get_authenticator_common_for_testing() {
     return authenticator_common_.get();
   }
+#endif
 
   // mojom:Authenticator
   void MakeCredential(
@@ -70,7 +88,11 @@ class CONTENT_EXPORT AuthenticatorImpl
       IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) override;
   void Cancel() override;
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  std::unique_ptr<AuthenticatorCommonTizen> authenticator_common_tizen_;
+#else
   std::unique_ptr<AuthenticatorCommon> authenticator_common_;
+#endif
 
   // Owns pipes to this Authenticator from |render_frame_host_|.
   mojo::Receiver<blink::mojom::Authenticator> receiver_{this};
index 17a05a721309ceaf104d51f533e533ef2abb0295..c8a09ada8aad06cead3b086692372201c58194c2 100644 (file)
@@ -392,7 +392,10 @@ class CONTENT_EXPORT WebContentsDelegate {
   virtual void DidEdgeScrollBy(const gfx::Point& offset, bool handled) {}
 
   virtual void UpdateTooltipUnderCursor(const std::u16string& text) {}
-
+#if defined(USE_EFL)
+  virtual void DisplayQRCode(std::string contents) {}
+  virtual void CloseQRCode() {}
+#endif
   // Returns a pointer to a service to manage JavaScript dialogs. May return
   // nullptr in which case dialogs aren't shown.
   virtual JavaScriptDialogManager* GetJavaScriptDialogManager(
index 21a152285ce79375114b33fc155413ea39d1e7ff..fa70405eb2423b8538d2406f1c6d01bc1e696f3f 100755 (executable)
@@ -306,6 +306,12 @@ BuildRequires: vd_kernel-interfaces
 BuildRequires: pkgconfig(omxil-e4x12-v4l2)
 %endif
 
+%if "%{?_with_da_profile}" == "1"
+BuildRequires: libwebauthn-client, libwebauthn-client-devel, libwebauthn-common, webauthn, webauthn-ble
+BuildRequires: pkgconfig(capi-media-vision)
+BuildRequires: pkgconfig(capi-network-bluetooth)
+%endif
+
 # New Tizen HW Encoder API
 %if "%{__enable_hw_encoder}" == "1" && "%{?tizen_profile_name}" == "tv" && "%{ARCHITECTURE}" == "armv7l" && %{tizen_version} >= 70
 %define __enable_capi_encoder_tv_api 1
@@ -673,6 +679,9 @@ touch ./tizen_src/downloadable/ewk_api_wrapper_generator.py
 %if 0%{?_remove_webcore_debug_symbols:1}
   "remove_webcore_debug_symbols=true" \
 %endif
+%if "%{?_with_da_profile}" == "1"
+  "tizen_passkey_support=true" \
+%endif
 %if "%{?_local_build}" == "1"
   "use_symbolize=true" \
 %endif
index b8336482e3f62e91367866ad17848ef9e43a645d..ac7f693cd3fb312d55967915cb1cdd1eadcf3d59 100644 (file)
@@ -107,6 +107,27 @@ tizen_pkg_config("libecore-evas") {
 
 config("ecore-evas-public") {
 }
+if (tizen_passkey_support) {
+  config("webauthn") {
+    ldflags = [
+      "-lwebauthn-client",
+      "-lwebauthn-common",
+    ]
+  }
+  tizen_pkg_config("libwebauthn") {
+    packages = [ "webauthn" ]
+  }
+  config("capi-media-vision-barcode") {
+    ldflags = [
+      "-lmv_barcode_detector",
+      "-lmv_barcode_generator",
+      "-lmv_common",
+    ]
+   }
+  tizen_pkg_config("libcapi-media-vision-barcode") {
+    packages = [ "capi-media-vision-barcode" ]
+  }
+}
 
 config("atk") {
   ldflags = [ "-latk-1.0" ]
index 456b13f621853a9b5fa22459e75a327d12b335f3..3c3dad1920dc10693cd9dd57dcd22005ff8eaa2d 100644 (file)
@@ -45,6 +45,9 @@ config("tizen_feature_flags") {
         defines += [ "TIZEN_VIDEO_HOLE" ]
       }
     }
+    if (tizen_passkey_support) {
+      defines += [ "TIZEN_PASSKEY_SUPPORT" ]
+    }
     if (tizen_web_speech_recognition) {
       defines += [ "TIZEN_WEB_SPEECH_RECOGNITION" ]
     }
index 76ce22ba1d2a4c42e4c8e6d9913ef139c51c67da..a576dd9b9404558ed856c8611c040b2f9f5a8c48 100644 (file)
@@ -99,6 +99,7 @@ declare_args() {
   v8_unittests = false
   tizen_thread_booster_service = false
   tizen_rtc_unittests = false
+  tizen_passkey_support = false
 }
 
 if (use_ttrace) {
index 91bbe44de6b2b64e27df2e0afdcd43a49a483465..ec42fd5b0bc636147eafeee2cb5625870b5f67bd 100755 (executable)
@@ -215,11 +215,11 @@ url = http://168.219.244.109/products/tv/official/2020/ONEMAIN/emulator32/latest
 #
 #DA Family Hub 7.0 meson
 [repo.da_product_7.0_fhub_meson]
-url = http://10.113.136.26/snapshots/DA/Tizen-7.0/Tizen-7.0-DA-Unified/reference/repos/MESON64/packages/
+url = http://10.113.138.205/snapshots/DA/Tizen-7.0/Tizen-7.0-DA-Unified/reference/repos/MESON64/packages/
 
 #Tizen 7.0 Base
 [repo.da_product_7.0_base]
-url = http://10.113.136.26/snapshots/DA/Tizen-7.0/Tizen-7.0-DA-Base/reference/repos/standard/packages/
+url = http://10.113.138.205/snapshots/DA/Tizen-7.0/Tizen-7.0-DA-Base/reference/repos/standard/packages/
 
 ###############################################
 #
@@ -231,17 +231,27 @@ buildroot = ~/GBS-ROOT-TZDA_7.0_AARCH64-MESON
 user = blinkbot
 passwdx = QlpoOTFBWSZTWd0JOhUAAACBAABgIAAhAIIjF3JFOFCQ3Qk6FQ==
 
+###############################################
+#
+# Tizen v7.0 product DA (armv7l)
+#
+[profile.tzda_7.0_arm-meson]
+repos = repo.da_product_7.0_base, repo.da_product_7.0_fhub_meson
+buildroot = ~/GBS-ROOT-TZDA_7.0_ARM-MESON
+user = blinkbot
+passwdx = QlpoOTFBWSZTWd0JOhUAAACBAABgIAAhAIIjF3JFOFCQ3Qk6FQ==
+
 ###############################################
 #
 # Tizen v6.0 product DA
 #
 #DA Family Hub 6.0 kantm
 [repo.da_product_6.0_fhub_kantm]
-url = http://10.113.136.26/snapshots/DA/Tizen-6.0/Tizen-6.0-DA-FHUB/reference/repos/KANTM/packages/
+url = http://10.113.138.205/snapshots/DA/Tizen-6.0/Tizen-6.0-DA-FHUB/reference/repos/KANTM/packages/
 
 #Tizen 6.0 Base
 [repo.da_product_6.0_base]
-url = http://10.113.136.32/download/snapshots/tizen/6.0-da-base/latest/repos/standard/packages/
+url = http://10.113.138.205/download/snapshots/tizen/6.0-da-base/latest/repos/standard/packages/
 
 ###############################################
 #
index f47b53ab2adbc97a4ef603ec39efbe2895d4e428..53de7553b6fdc664333b32c89ee3e4d90e821328 100644 (file)
@@ -29,10 +29,14 @@ external_content_browser_efl_configs = [
   "//tizen_src/build:libtts",
 ]
 
-if (is_tizen) {
+if (tizen_passkey_support) {
   external_content_browser_efl_configs += [
     "//tizen_src/build:vconf",
     "//tizen_src/build:libvconf",
+    "//tizen_src/build:webauthn",
+    "//tizen_src/build:libwebauthn",
+    "//tizen_src/build:capi-media-vision-barcode",
+    "//tizen_src/build:libcapi-media-vision-barcode",
   ]
 }
 
@@ -202,6 +206,17 @@ if (is_tizen) {
   ]
 }
 
+if(tizen_passkey_support){
+  external_content_browser_efl_sources += [
+    "//tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.cc",
+    "//tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.h",
+  ]
+  external_exclude_content_browser_efl_sources += [
+    "webauth/authenticator_common.cc",
+    "webauth/authenticator_common.h",
+  ]
+}
+
 if (tizen_atk_support) {
   external_content_browser_efl_configs += [
     "//tizen_src/build:atk",
index 8616f6eff7fe04b6d8ccd593559dd8b8e07c5b0f..784057967570359a2871857a13eb7017be1f5196 100644 (file)
@@ -1008,6 +1008,28 @@ void RenderWidgetHostViewEfl::DidGetContentSnapshot(const SkBitmap& bitmap,
   screen_capture_cb_map_.Remove(request_id);
 }
 
+void RenderWidgetHostViewEfl::DisplayQRCode(std::string contents) {
+  web_contents_.GetDelegate()->DisplayQRCode(contents);
+}
+
+void RenderWidgetHostViewEfl::CloseQRCode() {
+  web_contents_.GetDelegate()->CloseQRCode();
+}
+
+#if defined(TIZEN_PASSKEY_SUPPORT)
+void RenderWidgetHostViewEfl::CancelAuthentication() {
+  // Get AuthenticatorCommonTizen reference to invoke the Cancel method
+  auto* rfh = static_cast<content::RenderFrameHostImpl*>(
+      web_contents_.GetFocusedFrame());
+  if (!rfh) {
+    return;
+  }
+  if (rfh->get_authenticator()) {
+    rfh->get_authenticator()->Cancel();
+  }
+}
+#endif
+
 void RenderWidgetHostViewEfl::BackgroundColorReceived(int callback_id,
                                                       SkColor bg_color) {
   web_contents_.GetDelegate()->BackgroundColorReceived(callback_id, bg_color);
index c82480226cd01b36011c7251942b50e934280650..5da3c7887d71168ec59eb99f7aa45c750ee7bf9f 100644 (file)
@@ -482,7 +482,11 @@ class CONTENT_EXPORT RenderWidgetHostViewEfl
       const base::RepeatingCallback<bool(void)>& on_mouse_up,
       const base::RepeatingCallback<void(void)>& on_mouse_move);
 #endif
-
+  void DisplayQRCode(std::string contents) override;
+  void CloseQRCode() override;
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  void CancelAuthentication();
+#endif
  protected:
   friend class RenderWidgetHostView;
 
diff --git a/tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.cc b/tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.cc
new file mode 100644 (file)
index 0000000..2b59227
--- /dev/null
@@ -0,0 +1,1489 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/webauthn/authenticator_common_tizen.h"
+
+#include <cstring>
+#include <iostream>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <typeinfo>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "base/base64url.h"
+#include "base/bind.h"
+#include "base/check.h"
+#include "base/command_line.h"
+#include "base/containers/contains.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/notreached.h"
+#include "base/rand_util.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/utf_string_conversion_utils.h"
+#include "base/timer/timer.h"
+#include "build/build_config.h"
+#include "build/chromeos_buildflags.h"
+#include "content/browser/bad_message.h"
+#include "content/browser/renderer_host/back_forward_cache_disable.h"
+#include "content/browser/webauth/authenticator_environment_impl.h"
+#include "content/browser/webauth/client_data_json.h"
+#include "content/browser/webauth/is_uvpaa.h"
+#include "content/browser/webauth/virtual_authenticator_request_delegate.h"
+#include "content/browser/webauth/virtual_fido_discovery_factory.h"
+#include "content/browser/webauth/webauth_request_security_checker.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/device_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
+#include "crypto/sha2.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cert/asn1_util.h"
+#include "net/der/input.h"
+#include "net/der/parse_values.h"
+#include "net/der/parser.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "url/url_constants.h"
+#include "url/url_util.h"
+
+#if defined(OS_MAC)
+#include "device/fido/mac/authenticator.h"
+#include "device/fido/mac/credential_metadata.h"
+#endif
+
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+#include "device/fido/cros/authenticator.h"
+#endif
+
+namespace content {
+
+// RequestExtension is a type of extension in a WebAuthn request that might
+// yield an extension output in the response.
+enum class RequestExtension {
+  kAppID,
+  kHMACSecret,
+  kPRF,
+  kCredProps,
+  kLargeBlobEnable,
+  kLargeBlobRead,
+  kLargeBlobWrite,
+  kCredBlob,
+  kGetCredBlob,
+};
+
+enum class AttestationErasureOption {
+  kIncludeAttestation,
+  kEraseAttestationButIncludeAaguid,
+  kEraseAttestationAndAaguid,
+};
+
+namespace {
+
+constexpr char kGstaticAppId[] =
+    "https://www.gstatic.com/securitykey/origins.json";
+constexpr char kGstaticCorpAppId[] =
+    "https://www.gstatic.com/securitykey/a/google.com/origins.json";
+
+WebAuthenticationDelegate* GetWebAuthenticationDelegate() {
+  return GetContentClient()->browser()->GetWebAuthenticationDelegate();
+}
+
+std::string Base64UrlEncode(const base::span<const uint8_t> input) {
+  std::string ret;
+  base::Base64UrlEncode(
+      base::StringPiece(reinterpret_cast<const char*>(input.data()),
+                        input.size()),
+      base::Base64UrlEncodePolicy::OMIT_PADDING, &ret);
+  return ret;
+}
+
+// Validates whether the given origin is authorized to use the provided App
+// ID value, mostly according to the rules in
+// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-appid-and-facets-v1.2-ps-20170411.html#determining-if-a-caller-s-facetid-is-authorized-for-an-appid.
+//
+// Returns the App ID to use for the request, or absl::nullopt if the origin
+// is not authorized to use the provided value.
+absl::optional<std::string> ProcessAppIdExtension(
+    std::string appid,
+    const url::Origin& caller_origin) {
+  // The CryptoToken U2F extension checks the appid before calling the WebAuthn
+  // API so there is no need to validate it here.
+  if (WebAuthRequestSecurityChecker::OriginIsCryptoTokenExtension(
+          caller_origin)) {
+    if (!GURL(appid).is_valid()) {
+      DCHECK(false) << "cryptotoken request did not set a valid App ID";
+      return absl::nullopt;
+    }
+    return appid;
+  }
+
+  // Step 1: "If the AppID is not an HTTPS URL, and matches the FacetID of the
+  // caller, no additional processing is necessary and the operation may
+  // proceed."
+
+  // Webauthn is only supported on secure origins and |ValidateEffectiveDomain|
+  // has already checked this property of |caller_origin| before this call. Thus
+  // this step is moot.
+  // TODO(https://crbug.com/1158302): Use IsOriginPotentiallyTrustworthy?
+  DCHECK(network::IsUrlPotentiallyTrustworthy(caller_origin.GetURL()));
+
+  // Step 2: "If the AppID is null or empty, the client must set the AppID to be
+  // the FacetID of the caller, and the operation may proceed without additional
+  // processing."
+  if (appid.empty()) {
+    // While the U2F spec says to default the App ID to the Facet ID, which is
+    // the origin plus a trailing forward slash [1], cryptotoken and Firefox
+    // just use the site's Origin without trailing slash. We follow their
+    // implementations rather than the spec.
+    //
+    // [1]https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-appid-and-facets-v2.0-id-20180227.html#determining-the-facetid-of-a-calling-application
+    appid = caller_origin.Serialize();
+  }
+
+  // Step 3: "If the caller's FacetID is an https:// Origin sharing the same
+  // host as the AppID, (e.g. if an application hosted at
+  // https://fido.example.com/myApp set an AppID of
+  // https://fido.example.com/myAppId), no additional processing is necessary
+  // and the operation may proceed."
+  GURL appid_url = GURL(appid);
+  if (!appid_url.is_valid() || appid_url.scheme() != url::kHttpsScheme ||
+      appid_url.scheme_piece() != caller_origin.scheme()) {
+    return absl::nullopt;
+  }
+
+  // This check is repeated inside |SameDomainOrHost|, just after this. However
+  // it's cheap and mirrors the structure of the spec.
+  if (appid_url.host_piece() == caller_origin.host()) {
+    return appid;
+  }
+
+  // At this point we diverge from the specification in order to avoid the
+  // complexity of making a network request which isn't believed to be
+  // necessary in practice. See also
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=1244959#c8
+  if (net::registry_controlled_domains::SameDomainOrHost(
+          appid_url, caller_origin,
+          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+    return appid;
+  }
+
+  // As a compatibility hack, sites within google.com are allowed to assert two
+  // special-case AppIDs. Firefox also does this:
+  // https://groups.google.com/forum/#!msg/mozilla.dev.platform/Uiu3fwnA2xw/201ynAiPAQAJ
+  const GURL gstatic_appid(kGstaticAppId);
+  const GURL gstatic_corp_appid(kGstaticCorpAppId);
+  DCHECK(gstatic_appid.is_valid() && gstatic_corp_appid.is_valid());
+  if (caller_origin.DomainIs("google.com") && !appid_url.has_ref() &&
+      (appid_url.EqualsIgnoringRef(gstatic_appid) ||
+       appid_url.EqualsIgnoringRef(gstatic_corp_appid))) {
+    return appid;
+  }
+
+  return absl::nullopt;
+}
+
+// Returns an App ID string if a U2F credential must be made for the request
+// with |options|. This is the case for requests that either originate from
+// cryptotoken or have the googleLegacyAppidSupport extension set.
+absl::optional<std::string> MakeCredentialU2fAppIdOverride(
+    const url::Origin& caller_origin,
+    const blink::mojom::PublicKeyCredentialCreationOptionsPtr& options) {
+  // Cryptotoken passes the U2F request's App ID in the RP ID field of the
+  // WebAuthn request.
+  if (WebAuthRequestSecurityChecker::OriginIsCryptoTokenExtension(
+          caller_origin)) {
+    DCHECK(!options->google_legacy_app_id_support);
+    return options->relying_party.id;
+  }
+  if (options->google_legacy_app_id_support &&
+      options->relying_party.id == "google.com") {
+    if (caller_origin.DomainIs("login.corp.google.com")) {
+      return kGstaticCorpAppId;
+    }
+    return kGstaticAppId;
+  }
+  return absl::nullopt;
+}
+
+// The application parameter is the SHA-256 hash of the UTF-8 encoding of
+// the application identity (i.e. relying_party_id) of the application
+// requesting the registration.
+std::array<uint8_t, crypto::kSHA256Length> CreateApplicationParameter(
+    const std::string& relying_party_id) {
+  std::array<uint8_t, crypto::kSHA256Length> application_parameter;
+  crypto::SHA256HashString(relying_party_id, application_parameter.data(),
+                           application_parameter.size());
+  return application_parameter;
+}
+
+device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
+    const std::string& client_data_json,
+    const blink::mojom::PublicKeyCredentialRequestOptionsPtr& options,
+    absl::optional<std::string> app_id,
+    bool is_off_the_record) {
+  device::CtapGetAssertionRequest request_parameter(options->relying_party_id,
+                                                    client_data_json);
+
+  request_parameter.allow_list = options->allow_credentials;
+
+  request_parameter.user_verification = options->user_verification;
+
+  if (app_id) {
+    request_parameter.alternative_application_parameter =
+        CreateApplicationParameter(*app_id);
+    request_parameter.app_id = std::move(*app_id);
+  }
+
+  if (!options->cable_authentication_data.empty()) {
+    request_parameter.cable_extension = options->cable_authentication_data;
+  }
+  if (options->large_blob_read) {
+    request_parameter.large_blob_read = true;
+    request_parameter.large_blob_key = true;
+  }
+  if (options->large_blob_write) {
+    request_parameter.large_blob_key = true;
+  }
+  request_parameter.is_off_the_record_context = is_off_the_record;
+  return request_parameter;
+}
+
+
+base::TimeDelta AdjustTimeout(absl::optional<base::TimeDelta> timeout,
+                              RenderFrameHost* render_frame_host) {
+  // Time to wait for an authenticator to successfully complete an operation.
+  static constexpr base::TimeDelta kAdjustedTimeoutLower =
+      base::TimeDelta::FromSeconds(10);
+  static constexpr base::TimeDelta kAdjustedTimeoutUpper =
+      base::TimeDelta::FromMinutes(10);
+
+  if (!timeout) {
+    return kAdjustedTimeoutUpper;
+  }
+  const bool testing_api_enabled =
+      AuthenticatorEnvironmentImpl::GetInstance()
+          ->IsVirtualAuthenticatorEnabledFor(
+              static_cast<RenderFrameHostImpl*>(render_frame_host)
+                  ->frame_tree_node());
+  if (testing_api_enabled) {
+    return *timeout;
+  }
+  return std::max(kAdjustedTimeoutLower,
+                  std::min(kAdjustedTimeoutUpper, *timeout));
+}
+
+/* Webauthn  functions*/
+
+template <class T>
+wauthn_const_buffer_s ToWauthnConstBuff(T& x) noexcept {
+  static_assert(sizeof(decltype(*x.data())) == 1, "for reinterpret_cast below");
+  // reinterpret_cast is for std::string input values
+  return wauthn_const_buffer_s{reinterpret_cast<const uint8_t*>(x.data()),
+                               x.size()};
+}
+
+typedef std::vector<uint8_t> Buffer;
+
+Buffer ToBuffer(wauthn_const_buffer_s buff) {
+  return Buffer{buff.data, buff.data + buff.size};
+}
+
+struct LinkedData {
+  Buffer contactId;
+  Buffer linkId;
+  Buffer linkSecret;
+  Buffer authenticatorPubKey;
+  Buffer authenticatorName;
+  Buffer signature;
+  Buffer tunnelServerDomain;
+  Buffer identityKey;
+};
+
+template <class Bytes>
+std::string LowercaseHexStringOf(const Bytes& bytes) {
+  static_assert(sizeof(typename Bytes::value_type) == 1);
+  std::string res;
+  for (uint8_t byte : bytes) {
+    constexpr char digits[] = "0123456789abcdef";
+    res += digits[byte >> 4];
+    res += digits[byte & 15];
+  }
+  return res;
+}
+blink::mojom::AuthenticatorStatus WauthnErrorToAuthStatus(
+    wauthn_error_e result) {
+  switch (result) {
+    case WAUTHN_ERROR_NONE:
+      return blink::mojom::AuthenticatorStatus::SUCCESS;
+    case WAUTHN_ERROR_NONE_AND_WAIT:
+      return blink::mojom::AuthenticatorStatus::PENDING_REQUEST;
+    case WAUTHN_ERROR_PERMISSION_DENIED:
+    case WAUTHN_ERROR_ACCESS_DENIED:
+    case WAUTHN_ERROR_NOT_ALLOWED:
+    case WAUTHN_ERROR_CONNECTION_REFUSED:
+      return blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+    case WAUTHN_ERROR_TIMED_OUT:
+    case WAUTHN_ERROR_SOCKET:
+    case WAUTHN_ERROR_CANCELED:
+      return blink::mojom::AuthenticatorStatus::ABORT_ERROR;
+    case WAUTHN_ERROR_INVALID_STATE:
+    case WAUTHN_ERROR_ENCODING_FAILED:
+    case WAUTHN_ERROR_INVALID_PARAMETER:
+      return blink::mojom::AuthenticatorStatus::INVALID_DOMAIN;
+    case WAUTHN_ERROR_NO_SUCH_SERVICE:
+    case WAUTHN_ERROR_NOT_SUPPORTED:
+      return blink::mojom::AuthenticatorStatus::ANDROID_NOT_SUPPORTED_ERROR;
+    default:
+      return blink::mojom::AuthenticatorStatus::UNKNOWN_ERROR;
+  }
+}
+
+}  // namespace
+
+void AuthenticatorCommonTizen::DisplayQRCallback(const char* qr_contents,
+                                                 void* data) {
+  AuthenticatorCommonTizen* thiz =
+      reinterpret_cast<AuthenticatorCommonTizen*>(data);
+  std::string encoded(qr_contents);
+
+  RenderFrameHostImpl* const render_frame_host_impl =
+      static_cast<RenderFrameHostImpl*>(thiz->GetRenderFrameHost());
+
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE,
+      base::BindOnce(&RenderFrameHostImpl::DisplayQRCode,
+                     base::Unretained(render_frame_host_impl), encoded));
+}
+
+void AuthenticatorCommonTizen::MCCallback(
+    const wauthn_pubkey_credential_attestation_s* pubkey_cred,
+    wauthn_error_e result,
+    void* data) {
+  if (result == WAUTHN_ERROR_CANCELED) {
+    return;
+  }
+  AuthenticatorCommonTizen* thiz =
+      reinterpret_cast<AuthenticatorCommonTizen*>(data);
+
+  RenderFrameHostImpl* const render_frame_host_impl =
+      static_cast<RenderFrameHostImpl*>(thiz->GetRenderFrameHost());
+
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE, base::BindOnce(&RenderFrameHostImpl::CloseQRCode,
+                                base::Unretained(render_frame_host_impl)));
+
+  if (!thiz->make_credential_response_callback_) {
+     return;
+   }
+
+  if (!pubkey_cred || result != WAUTHN_ERROR_NONE) {
+    thiz->CompleteMakeCredentialRequest(WauthnErrorToAuthStatus(result));
+    return;
+  }
+
+  thiz->CompleteMakeCredentialRequest(
+      blink::mojom::AuthenticatorStatus::SUCCESS,
+      thiz->CreateMakeCredentialResponse(std::move(pubkey_cred),
+                                         AttestationErasureOption::kEraseAttestationAndAaguid),
+      Focus::kDoCheck);
+}
+
+void AuthenticatorCommonTizen::GACallback(
+    const wauthn_pubkey_credential_assertion_s* pubkey_cred,
+    wauthn_error_e result,
+    void* data) {
+  if (result == WAUTHN_ERROR_CANCELED) {
+    return;
+  }
+  AuthenticatorCommonTizen* thiz =
+      reinterpret_cast<AuthenticatorCommonTizen*>(data);
+
+  RenderFrameHostImpl* const render_frame_host_impl =
+      static_cast<RenderFrameHostImpl*>(thiz->GetRenderFrameHost());
+
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE, base::BindOnce(&RenderFrameHostImpl::CloseQRCode,
+                                base::Unretained(render_frame_host_impl)));
+
+  if (!thiz->get_assertion_response_callback_) {
+    return;
+  }
+
+  if (!pubkey_cred || result != WAUTHN_ERROR_NONE) {
+    thiz->CompleteGetAssertionRequest(WauthnErrorToAuthStatus(result));
+    return;
+  }
+
+  thiz->CompleteGetAssertionRequest(
+      blink::mojom::AuthenticatorStatus::SUCCESS,
+      thiz->CreateGetAssertionResponse(std::move(pubkey_cred)));
+}
+void AuthenticatorCommonTizen::MCUpdateLinkedDataCallback(
+    const wauthn_hybrid_linked_data_s* linked_data,
+    wauthn_error_e result,
+    void* data) {
+  NOTIMPLEMENTED();
+}
+
+void AuthenticatorCommonTizen::GAUpdateLinkedDataCallback(
+    const wauthn_hybrid_linked_data_s* linked_data,
+    wauthn_error_e result,
+    void* data) {
+  NOTIMPLEMENTED();
+}
+AuthenticatorCommonTizen::AuthenticatorCommonTizen(
+    RenderFrameHost* render_frame_host)
+    : render_frame_host_id_(render_frame_host->GetGlobalId()),
+      security_checker_(static_cast<RenderFrameHostImpl*>(render_frame_host)
+                            ->GetWebAuthRequestSecurityChecker()) {
+  // Disable the back-forward cache for any document that makes WebAuthn
+  // requests. Pages using privacy-sensitive APIs are generally exempt from
+  // back-forward cache for now as a precaution.
+  BackForwardCache::DisableForRenderFrameHost(
+      render_frame_host,
+      BackForwardCacheDisable::DisabledReason(
+          BackForwardCacheDisable::DisabledReasonId::kWebAuthenticationAPI));
+}
+
+AuthenticatorCommonTizen::~AuthenticatorCommonTizen() {
+  // Resolve pending callbacks before disconnecting the receiver.
+  if (make_credential_response_callback_) {
+    CompleteMakeCredentialRequest(
+        blink::mojom::AuthenticatorStatus::UNKNOWN_ERROR);
+  }
+  if (get_assertion_response_callback_) {
+    CompleteGetAssertionRequest(
+        blink::mojom::AuthenticatorStatus::UNKNOWN_ERROR);
+  }
+}
+
+std::unique_ptr<AuthenticatorRequestClientDelegate>
+AuthenticatorCommonTizen::MaybeCreateRequestDelegate() {
+  RenderFrameHostImpl* const render_frame_host_impl =
+      static_cast<RenderFrameHostImpl*>(GetRenderFrameHost());
+  if (AuthenticatorEnvironmentImpl::GetInstance()
+          ->IsVirtualAuthenticatorEnabledFor(
+              render_frame_host_impl->frame_tree_node())) {
+    return std::make_unique<VirtualAuthenticatorRequestDelegate>();
+  }
+  return GetContentClient()->browser()->GetWebAuthenticationRequestDelegate(
+      render_frame_host_impl);
+}
+
+bool AuthenticatorCommonTizen::IsFocused() const {
+  return GetRenderFrameHost()->IsActive() &&
+         GetWebAuthenticationDelegate()->IsFocused(
+             WebContents::FromRenderFrameHost(GetRenderFrameHost()));
+}
+void AuthenticatorCommonTizen::PopulateMCWebauthnArgs(
+    blink::mojom::PublicKeyCredentialCreationOptionsPtr options) {
+  std::memset(&mc_options_, 0, sizeof(mc_options_));
+
+  // Chrome clientData -> Webauthn clientData
+  client_data_json_buff_ = ToWauthnConstBuff(client_data_json_);
+  mc_client_data_.client_data_json = &client_data_json_buff_;
+  mc_client_data_.hash_alg = WAUTHN_HASH_ALGORITHM_SHA_256;
+
+  // Chrome RP -> Webauthn RP
+  rel_party_id_ = options->relying_party.id;
+  rp_.id = rel_party_id_.c_str();
+
+  // options->relying_party.name is of type std::optional(std::string)
+  if (options->relying_party.name) {
+    rel_party_name_ = options->relying_party.name.value();
+    rp_.name = rel_party_name_.c_str();
+  }
+
+  // Chrome User -> Webauthn User
+  user_id_vector_ = options->user.id;
+  user_id_buff_ = ToWauthnConstBuff(user_id_vector_);
+  user_.id = &user_id_buff_;
+
+  user_name_string_ = *options->user.name;
+  user_.name = user_name_string_.c_str();
+
+  user_display_name_string_ = *options->user.display_name;
+  user_.display_name = user_display_name_string_.c_str();
+
+  // Chrome Pubkey Params -> Webauthn Pubkey Params
+  std::unordered_map<int, wauthn_cose_algorithm_e>
+      mapping_identifier_to_algorithm;
+  mapping_identifier_to_algorithm[-7] =
+      WAUTHN_COSE_ALGORITHM_ECDSA_P256_WITH_SHA256;
+  mapping_identifier_to_algorithm[-35] =
+      WAUTHN_COSE_ALGORITHM_ECDSA_P384_WITH_SHA384;
+  mapping_identifier_to_algorithm[-36] =
+      WAUTHN_COSE_ALGORITHM_ECDSA_P521_WITH_SHA512;
+  mapping_identifier_to_algorithm[-8] = WAUTHN_COSE_ALGORITHM_EDDSA;
+  mapping_identifier_to_algorithm[-37] =
+      WAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA256;
+  mapping_identifier_to_algorithm[-38] =
+      WAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA384;
+  mapping_identifier_to_algorithm[-39] =
+      WAUTHN_COSE_ALGORITHM_RSA_PSS_WITH_SHA512;
+  mapping_identifier_to_algorithm[-257] =
+      WAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA256;
+  mapping_identifier_to_algorithm[-258] =
+      WAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA384;
+  mapping_identifier_to_algorithm[-259] =
+      WAUTHN_COSE_ALGORITHM_RSASSA_PKCS1_V1_5_WITH_SHA512;
+
+  int num_pubkey_params = options->public_key_parameters.size();
+  params_vector_ = std::vector<wauthn_pubkey_cred_param_s>(num_pubkey_params);
+  for (int iter = 0; iter < num_pubkey_params; iter++) {
+    params_vector_[iter].type = WAUTHN_PUBKEY_CRED_TYPE_PUBLIC_KEY;
+    params_vector_[iter].alg =
+        mapping_identifier_to_algorithm[options->public_key_parameters[iter]
+                                            .algorithm];
+  }
+  pubkey_cred_params_.params = &params_vector_[0];
+  pubkey_cred_params_.size = num_pubkey_params;
+
+  // Chrome Timeout -> Webauthn Timeout
+  if (options->timeout) {
+    mc_options_.timeout = options->timeout->InMilliseconds();
+  }
+
+  // Chrome Excluded Credentials -> Webauthn Excluded Credentials
+  if (!options->exclude_credentials.empty()) {
+    std::unordered_map<device::FidoTransportProtocol, unsigned int>
+        mapping_transport_to_unsigned_int;
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kUsbHumanInterfaceDevice] = 0x00000001;
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kNearFieldCommunication] = 0x00000002;
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kBluetoothLowEnergy] = 0x00000004;
+    // mapping_transport_to_unsigned_int[device::FidoTransportProtocol::kHybrid] =
+    //     0x00000010;                 check this
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kInternal] = 0x00000020;
+
+    int num_excluded_credentials = options->exclude_credentials.size();
+   excluded_creds_vector_ =
+        std::vector<wauthn_pubkey_cred_descriptor_s>(num_excluded_credentials);
+    excluded_creds_id_buffer_vector_ =
+        std::vector<wauthn_const_buffer_s>(num_excluded_credentials);
+    excluded_creds_id_int8_vector_ =
+        std::vector<std::vector<uint8_t>>(num_excluded_credentials);
+
+    for (int iter = 0; iter < num_excluded_credentials; iter++) {
+      excluded_creds_id_int8_vector_[iter] =
+          options->exclude_credentials[iter].id();
+      excluded_creds_id_buffer_vector_[iter] =
+          ToWauthnConstBuff(excluded_creds_id_int8_vector_[iter]);
+      excluded_creds_vector_[iter].id = &excluded_creds_id_buffer_vector_[iter];
+      excluded_creds_vector_[iter].type = WAUTHN_PUBKEY_CRED_TYPE_PUBLIC_KEY;
+
+      if (!options->exclude_credentials[iter].transports().empty()) {
+        excluded_creds_vector_[iter].transports = 0x00000000;
+        for (auto iter_exclude_credential =
+                 options->exclude_credentials[iter].transports().begin();
+             iter_exclude_credential !=
+             options->exclude_credentials[iter].transports().end();
+             iter_exclude_credential++) {
+          excluded_creds_vector_[iter].transports |=
+              mapping_transport_to_unsigned_int[*iter_exclude_credential];
+        }
+      }
+    }
+    excluded_credentials_.descriptors = &excluded_creds_vector_[0];
+    excluded_credentials_.size = num_excluded_credentials;
+    mc_options_.exclude_credentials = &excluded_credentials_;
+  }
+
+  // Chrome Authenticator Selection -> Webauthn Authenticator Selection
+  if (options->authenticator_selection) {
+    if (options->authenticator_selection->authenticator_attachment() !=
+        device::AuthenticatorAttachment::kAny) {
+      mc_authenticator_selection_criteria_.attachment =
+          options->authenticator_selection->authenticator_attachment() ==
+                  device::AuthenticatorAttachment::kPlatform
+              ? WAUTHN_AUTHENTICATOR_ATTACHMENT_PLATFORM
+              : WAUTHN_AUTHENTICATOR_ATTACHMENT_CROSS_PLATFORM;
+    }
+
+    switch (options->authenticator_selection->resident_key()) {
+      case device::ResidentKeyRequirement::kDiscouraged:
+        mc_authenticator_selection_criteria_.resident_key =
+            WAUTHN_RESIDENT_KEY_REQUIREMENT_DISCOURAGED;
+        break;
+      case device::ResidentKeyRequirement::kPreferred:
+        mc_authenticator_selection_criteria_.resident_key =
+            WAUTHN_RESIDENT_KEY_REQUIREMENT_PREFERRED;
+        break;
+      case device::ResidentKeyRequirement::kRequired:
+        mc_authenticator_selection_criteria_.resident_key =
+            WAUTHN_RESIDENT_KEY_REQUIREMENT_REQUIRED;
+    }
+    mc_authenticator_selection_criteria_.require_resident_key =
+        mc_authenticator_selection_criteria_.resident_key ==
+        WAUTHN_RESIDENT_KEY_REQUIREMENT_REQUIRED;
+
+    switch (options->authenticator_selection->user_verification_requirement()) {
+      case device::UserVerificationRequirement::kRequired:
+        mc_authenticator_selection_criteria_.user_verification =
+            WAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
+        break;
+      case device::UserVerificationRequirement::kPreferred:
+        mc_authenticator_selection_criteria_.user_verification =
+            WAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
+        break;
+      case device::UserVerificationRequirement::kDiscouraged:
+        mc_authenticator_selection_criteria_.user_verification =
+            WAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
+    }
+    mc_options_.authenticator_selection = &mc_authenticator_selection_criteria_;
+  }
+
+
+  // Chrome Attestation Preference -> Webauthn Attestation Preference
+  switch (options->attestation) {
+    case ::device::AttestationConveyancePreference::kIndirect:
+      mc_options_.attestation = WAUTHN_ATTESTATION_PREF_INDIRECT;
+      break;
+    case ::device::AttestationConveyancePreference::kDirect:
+      mc_options_.attestation = WAUTHN_ATTESTATION_PREF_DIRECT;
+      break;
+    case ::device::AttestationConveyancePreference::
+        kEnterpriseIfRPListedOnAuthenticator:
+    case ::device::AttestationConveyancePreference::
+        kEnterpriseApprovedByBrowser:
+      mc_options_.attestation = WAUTHN_ATTESTATION_PREF_ENTERPRISE;
+      break;
+    default:
+      mc_options_.attestation = WAUTHN_ATTESTATION_PREF_NONE;
+  }
+
+  mc_options_.rp = &rp_;
+  mc_options_.user = &user_;
+  mc_options_.pubkey_cred_params = &pubkey_cred_params_;
+
+  // Chrome extensions -> Webauthn Extensions
+  mc_extension_id_buffer_vector_.clear();
+  mc_extension_value_buffer_vector_.clear();
+  mc_extensions_vector_.clear();
+  extension_value_ = std::vector<std::string>(17, "");
+
+  if (options->hmac_create_secret) {
+    extension_value_[12] = "true";
+  }
+
+  switch (options->protection_policy) {
+    case blink::mojom::ProtectionPolicy::NONE:
+      extension_value_[8] = "NONE";
+      break;
+    case blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED:
+      extension_value_[8] = "UV_OR_CRED_ID_REQUIRED";
+      break;
+    case blink::mojom::ProtectionPolicy::UV_REQUIRED:
+      extension_value_[8] = "UV_REQUIRED";
+      break;
+  }
+
+  if (options->appid_exclude) {
+    extension_value_[13] = options->appid_exclude.value();
+  }
+
+  if (options->cred_props) {
+    extension_value_[14] = "true";
+  }
+
+  switch (options->large_blob_enable) {
+    case ::device::LargeBlobSupport::kRequired:
+      extension_value_[15] = "REQUIRED";
+      break;
+    case ::device::LargeBlobSupport::kPreferred:
+      extension_value_[15] = "PREFERRED";
+      break;
+  }
+
+  if (options->is_payment_credential_creation) {
+    extension_value_[16] = "true";
+  }
+
+  if (options->cred_blob) {
+    extension_value_[9].assign(options->cred_blob.value().begin(),
+                               options->cred_blob.value().end());
+  }
+
+  for (int iter = 0; iter < 17; iter++) {
+    if (extension_value_[iter].size()) {
+      mc_extension_id_buffer_vector_.push_back(
+          ToWauthnConstBuff(extension_id_[iter]));
+      mc_extension_value_buffer_vector_.push_back(
+          ToWauthnConstBuff(extension_value_[iter]));
+    }
+  }
+  int num_extensions = mc_extension_id_buffer_vector_.size();
+  mc_extensions_vector_ =
+      std::vector<wauthn_authentication_ext_s>(num_extensions);
+  for (int iter = 0; iter < num_extensions; iter++) {
+    mc_extensions_vector_[iter].extension_id =
+        &mc_extension_id_buffer_vector_[iter];
+    mc_extensions_vector_[iter].extension_value =
+        &mc_extension_value_buffer_vector_[iter];
+  }
+  mc_extensions_.extensions = &mc_extensions_vector_[0];
+  mc_extensions_.size = num_extensions;
+  mc_options_.extensions = &mc_extensions_;
+  mc_callbacks_.qrcode_callback = DisplayQRCallback;
+  mc_callbacks_.response_callback = MCCallback;
+  mc_callbacks_.linked_data_callback = MCUpdateLinkedDataCallback;
+  mc_callbacks_.user_data = this;
+}
+
+void AuthenticatorCommonTizen::PopulateGAWebauthnArgs(
+    blink::mojom::PublicKeyCredentialRequestOptionsPtr options) {
+  std::memset(&ga_options_, 0, sizeof(ga_options_));
+
+  client_data_json_buff_ = ToWauthnConstBuff(client_data_json_);
+
+  ga_client_data_.client_data_json = &client_data_json_buff_;
+  ga_client_data_.hash_alg = WAUTHN_HASH_ALGORITHM_SHA_256;
+
+  // Chrome Timeout -> Webauthn Timeout
+  if (options->timeout) {
+    ga_options_.timeout = options->timeout->InMilliseconds();
+  }
+
+  // Chrome RP -> Webauthn RP
+  rp_id_string_ = options->relying_party_id;
+
+  // Chrome Allow Credentials -> Webauthn Allow Credentials
+  if (!options->allow_credentials.empty()) {
+    std::unordered_map<device::FidoTransportProtocol, unsigned int>
+        mapping_transport_to_unsigned_int;
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kUsbHumanInterfaceDevice] = 0x00000001;
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kNearFieldCommunication] = 0x00000002;
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kBluetoothLowEnergy] = 0x00000004;
+    // mapping_transport_to_unsigned_int[device::FidoTransportProtocol::kHybrid] =
+    //     0x00000010;
+    mapping_transport_to_unsigned_int
+        [device::FidoTransportProtocol::kInternal] = 0x00000020;
+
+    int num_allow_credentials = options->allow_credentials.size();
+        pubkey_cred_descriptor_vector_ =
+        std::vector<wauthn_pubkey_cred_descriptor_s>(num_allow_credentials);
+    pubkey_cred_id_int8_vector_ =
+        std::vector<std::vector<uint8_t>>(num_allow_credentials);
+    pubkey_cred_id_buffer_vector_ =
+        std::vector<wauthn_const_buffer_s>(num_allow_credentials);
+
+    for (int iter = 0; iter < num_allow_credentials; iter++) {
+      pubkey_cred_id_int8_vector_[iter] = options->allow_credentials[iter].id();
+      pubkey_cred_id_buffer_vector_[iter] =
+          ToWauthnConstBuff(pubkey_cred_id_int8_vector_[iter]);
+      pubkey_cred_descriptor_vector_[iter].id =
+          &pubkey_cred_id_buffer_vector_[iter];
+      pubkey_cred_descriptor_vector_[iter].type =
+          WAUTHN_PUBKEY_CRED_TYPE_PUBLIC_KEY;
+
+      pubkey_cred_descriptor_vector_[iter].transports = 0x00000000;
+      for (const auto& transport :
+           options->allow_credentials[iter].transports()) {
+        pubkey_cred_descriptor_vector_[iter].transports |=
+            mapping_transport_to_unsigned_int[transport];
+      }
+    }
+    pubkey_cred_descriptors_.descriptors = &pubkey_cred_descriptor_vector_[0];
+    pubkey_cred_descriptors_.size = num_allow_credentials;
+
+    ga_options_.allow_credentials = &pubkey_cred_descriptors_;
+  }
+
+  // Chrome User Verification -> Webauthn User Verification
+  switch (options->user_verification) {
+    case device::UserVerificationRequirement::kRequired:
+      ga_options_.user_verification =
+          WAUTHN_USER_VERIFICATION_REQUIREMENT_REQUIRED;
+      break;
+    case device::UserVerificationRequirement::kPreferred:
+      ga_options_.user_verification =
+          WAUTHN_USER_VERIFICATION_REQUIREMENT_PREFERRED;
+      break;
+    case device::UserVerificationRequirement::kDiscouraged:
+      ga_options_.user_verification =
+          WAUTHN_USER_VERIFICATION_REQUIREMENT_DISCOURAGED;
+    default:
+      ga_options_.user_verification = WAUTHN_USER_VERIFICATION_REQUIREMENT_NONE;
+  }
+
+  ga_options_.rpId = rp_id_string_.c_str();
+  ga_options_.attestation = device_attestation_;
+
+  // Chrome extensions -> Webauthn Extensions
+  ga_extension_id_buffer_vector_.clear();
+  ga_extension_value_buffer_vector_.clear();
+  ga_extensions_vector_.clear();
+  extension_value_ = std::vector<std::string>(17, "");
+
+  if (options->appid) {
+    extension_value_[0] = options->appid.value();
+  }
+
+  for (int iter = 0; iter < 17; iter++) {
+    if (extension_value_[iter].size()) {
+      ga_extension_id_buffer_vector_.push_back(
+          ToWauthnConstBuff(extension_id_[iter]));
+      ga_extension_value_buffer_vector_.push_back(
+          ToWauthnConstBuff(extension_value_[iter]));
+    }
+  }
+  int num_extensions = ga_extension_id_buffer_vector_.size();
+  ga_extensions_vector_ =
+      std::vector<wauthn_authentication_ext_s>(num_extensions);
+  for (int iter = 0; iter < num_extensions; iter++) {
+    ga_extensions_vector_[iter].extension_id =
+        &ga_extension_id_buffer_vector_[iter];
+    ga_extensions_vector_[iter].extension_value =
+        &ga_extension_value_buffer_vector_[iter];
+  }
+  ga_extensions_.extensions = &ga_extensions_vector_[0];
+  ga_extensions_.size = num_extensions;
+  ga_options_.extensions = &ga_extensions_;
+  ga_callbacks_.qrcode_callback = DisplayQRCallback;
+  ga_callbacks_.response_callback = GACallback;
+  ga_callbacks_.linked_data_callback = GAUpdateLinkedDataCallback;
+  ga_callbacks_.user_data = this;
+}
+
+void AuthenticatorCommonTizen::OnLargeBlobCompressed(
+    data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result) {
+  // ctap_get_assertion_request_->large_blob_write =
+  //     device::fido_parsing_utils::MaterializeOrNull(result.value);
+  // StartGetAssertionRequest(/*allow_skipping_pin_touch=*/true);
+}
+
+void AuthenticatorCommonTizen::OnLargeBlobUncompressed(
+    device::AuthenticatorGetAssertionResponse response,
+    data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result) {
+  response.large_blob =
+      device::fido_parsing_utils::MaterializeOrNull(result.value);
+  CompleteGetAssertionRequest(
+      blink::mojom::AuthenticatorStatus::SUCCESS, nullptr);
+}
+
+// mojom::Authenticator
+void AuthenticatorCommonTizen::MakeCredential(
+    url::Origin caller_origin,
+    blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
+    blink::mojom::Authenticator::MakeCredentialCallback callback) {
+  if (request_) {
+    if (WebAuthRequestSecurityChecker::OriginIsCryptoTokenExtension(
+            caller_origin)) {
+      // Requests originating from cryptotoken will generally outlive any
+      // navigation events on the tab of the request's sender. Evict pending
+      // requests if cryptotoken sends a new one such that requests from before
+      // a navigation event do not prevent new requests. See
+      // https://crbug.com/935480.
+      CancelWithStatus(blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
+    } else {
+      std::move(callback).Run(
+          blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+      return;
+    }
+  }
+  DCHECK(!request_);
+  DCHECK(make_credential_response_callback_.is_null());
+  make_credential_response_callback_ = std::move(callback);
+
+  bool is_cross_origin;
+  blink::mojom::AuthenticatorStatus status =
+      security_checker_->ValidateAncestorOrigins(
+          caller_origin,
+          options->is_payment_credential_creation
+              ? WebAuthRequestSecurityChecker::RequestType::
+                    kMakePaymentCredential
+              : WebAuthRequestSecurityChecker::RequestType::kMakeCredential,
+          &is_cross_origin);
+  if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
+    CompleteMakeCredentialRequest(status);
+    return;
+  }
+
+  request_delegate_ = MaybeCreateRequestDelegate();
+  if (!request_delegate_) {
+    CompleteMakeCredentialRequest(
+        blink::mojom::AuthenticatorStatus::PENDING_REQUEST);
+    return;
+  }
+
+  absl::optional<std::string> rp_id =
+      GetWebAuthenticationDelegate()->MaybeGetRelyingPartyIdOverride(
+          options->relying_party.id, caller_origin);
+
+  if (!rp_id) {
+    // If the delegate didn't override RP ID selection then apply standard
+    // rules.
+    rp_id = std::move(options->relying_party.id);
+    status = security_checker_->ValidateDomainAndRelyingPartyID(caller_origin,
+                                                                *rp_id);
+    if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
+      CompleteMakeCredentialRequest(status);
+      return;
+    }
+  }
+
+  caller_origin_ = caller_origin;
+  relying_party_id_ = *rp_id;
+  options->relying_party.id = std::move(*rp_id);
+  request_delegate_->SetRelyingPartyId(relying_party_id_);
+
+  absl::optional<std::string> appid_exclude;
+  if (options->appid_exclude) {
+    appid_exclude =
+        ProcessAppIdExtension(*options->appid_exclude, caller_origin);
+    if (!appid_exclude) {
+      CompleteMakeCredentialRequest(
+          blink::mojom::AuthenticatorStatus::INVALID_DOMAIN);
+      return;
+    }
+  }
+
+  if (options->user.icon_url) {
+    status = security_checker_->ValidateAPrioriAuthenticatedUrl(
+        *options->user.icon_url);
+  }
+  if (status == blink::mojom::AuthenticatorStatus::SUCCESS &&
+      options->relying_party.icon_url) {
+    status = security_checker_->ValidateAPrioriAuthenticatedUrl(
+        *options->relying_party.icon_url);
+  }
+  if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
+    bad_message::ReceivedBadMessage(GetRenderFrameHost()->GetProcess(),
+                                    bad_message::AUTH_INVALID_ICON_URL);
+    CompleteMakeCredentialRequest(status);
+    return;
+  }
+
+  if (!IsFocused()) {
+    CompleteMakeCredentialRequest(
+        blink::mojom::AuthenticatorStatus::NOT_FOCUSED);
+    return;
+  }
+
+  const device::AuthenticatorSelectionCriteria
+      authenticator_selection_criteria =
+          options->authenticator_selection
+              ? *options->authenticator_selection
+              : device::AuthenticatorSelectionCriteria();
+
+  // Reject any non-sensical credProtect extension values.
+  if (  // Can't require the default policy (or no policy).
+      (options->enforce_protection_policy &&
+       (options->protection_policy ==
+            blink::mojom::ProtectionPolicy::UNSPECIFIED ||
+        options->protection_policy == blink::mojom::ProtectionPolicy::NONE)) ||
+      // For non-resident keys, NONE doesn't make sense. (UV_OR_CRED_ID_REQUIRED
+      // does because, with CTAP 2.0, just because a resident key isn't
+      // _required_ doesn't mean that one won't be created and an RP might want
+      // credProtect to take effect if that happens.)
+      (options->protection_policy == blink::mojom::ProtectionPolicy::NONE) ||
+      // UV_REQUIRED only makes sense if UV is required overall.
+      (options->protection_policy ==
+           blink::mojom::ProtectionPolicy::UV_REQUIRED &&
+       authenticator_selection_criteria.user_verification_requirement() !=
+           device::UserVerificationRequirement::kRequired)) {
+    CompleteMakeCredentialRequest(
+        blink::mojom::AuthenticatorStatus::PROTECTION_POLICY_INCONSISTENT);
+    return;
+  }
+
+  absl::optional<device::CredProtectRequest> cred_protect_request;
+  switch (options->protection_policy) {
+    case blink::mojom::ProtectionPolicy::UNSPECIFIED:
+      break;
+    case blink::mojom::ProtectionPolicy::NONE:
+      cred_protect_request = device::CredProtectRequest::kUVOptional;
+      break;
+    case blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED:
+      cred_protect_request = device::CredProtectRequest::kUVOrCredIDRequired;
+      break;
+    case blink::mojom::ProtectionPolicy::UV_REQUIRED:
+      cred_protect_request = device::CredProtectRequest::kUVRequired;
+      break;
+  }
+
+  timer_->Start(
+      FROM_HERE, AdjustTimeout(options->timeout, GetRenderFrameHost()),
+      base::BindOnce(&AuthenticatorCommonTizen::OnTimeout, base::Unretained(this)));
+
+  // Cryptotoken requests, making payment credentials, and Touch-to-Autofill
+  // should be proxied without UI.
+  const bool origin_is_crypto_token_extension =
+      WebAuthRequestSecurityChecker::OriginIsCryptoTokenExtension(
+          caller_origin);
+  if (origin_is_crypto_token_extension ||
+      (!base::FeatureList::IsEnabled(
+           features::kSecurePaymentConfirmationAPIV3) &&
+       options->is_payment_credential_creation) ||
+      disable_ui_) {
+    request_delegate_->DisableUI();
+  }
+
+  if (origin_is_crypto_token_extension) {
+    // Cryptotoken passes the real caller origin in |relying_party.name|.
+    const url::Origin client_data_origin =
+        url::Origin::Create(GURL(*options->relying_party.name));
+    client_data_json_ = BuildClientDataJson(
+        ClientDataRequestType::kU2fRegister, client_data_origin.Serialize(),
+        options->challenge, is_cross_origin);
+  } else {
+    // Regular WebAuthn request
+    client_data_json_ = BuildClientDataJson(
+        ClientDataRequestType::kWebAuthnCreate, caller_origin_.Serialize(),
+        options->challenge, is_cross_origin);
+  }
+
+  PopulateMCWebauthnArgs(std::move(options));
+  int ret =
+      wauthn_make_credential(&mc_client_data_, &mc_options_, &mc_callbacks_);
+  if (ret != WAUTHN_ERROR_NONE)
+    Cancel();
+}
+
+// mojom:Authenticator
+void AuthenticatorCommonTizen::GetAssertion(
+    url::Origin caller_origin,
+    blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
+    blink::mojom::PaymentOptionsPtr payment,
+    blink::mojom::Authenticator::GetAssertionCallback callback) {
+  if (request_) {
+    if (WebAuthRequestSecurityChecker::OriginIsCryptoTokenExtension(
+            caller_origin)) {
+      // Requests originating from cryptotoken will generally outlive any
+      // navigation events on the tab of the request's sender. Evict pending
+      // requests if cryptotoken sends a new one such that requests from before
+      // a navigation event do not prevent new requests. See
+      // https://crbug.com/935480.
+      CancelWithStatus(blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
+    } else {
+      std::move(callback).Run(
+          blink::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
+      return;
+    }
+  }
+  DCHECK(!request_);
+  DCHECK(get_assertion_response_callback_.is_null());
+  get_assertion_response_callback_ = std::move(callback);
+
+  bool is_cross_origin;
+  blink::mojom::AuthenticatorStatus status =
+      security_checker_->ValidateAncestorOrigins(
+          caller_origin,
+          WebAuthRequestSecurityChecker::RequestType::kGetAssertion,
+          &is_cross_origin);
+  if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
+    CompleteGetAssertionRequest(status);
+    return;
+  }
+
+  request_delegate_ = MaybeCreateRequestDelegate();
+  if (!request_delegate_) {
+    CompleteGetAssertionRequest(
+        blink::mojom::AuthenticatorStatus::PENDING_REQUEST);
+    return;
+  }
+
+  absl::optional<std::string> rp_id =
+      GetWebAuthenticationDelegate()->MaybeGetRelyingPartyIdOverride(
+          options->relying_party_id, caller_origin);
+
+  if (!rp_id) {
+    // If the delegate didn't override RP ID selection then apply standard
+    // rules.
+    status = security_checker_->ValidateDomainAndRelyingPartyID(
+        caller_origin, options->relying_party_id);
+    if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
+      CompleteGetAssertionRequest(status);
+      return;
+    }
+
+    rp_id = std::move(options->relying_party_id);
+  }
+
+  caller_origin_ = caller_origin;
+  relying_party_id_ = *rp_id;
+  options->relying_party_id = std::move(*rp_id);
+  request_delegate_->SetRelyingPartyId(relying_party_id_);
+
+  const bool origin_is_crypto_token_extension =
+      WebAuthRequestSecurityChecker::OriginIsCryptoTokenExtension(
+          caller_origin_);
+
+  if (origin_is_crypto_token_extension) {
+    // Cryptotoken provides the sender origin for U2F sign requests in the
+    // |relying_party_id| attribute.
+    client_data_json_ = BuildClientDataJson(
+        ClientDataRequestType::kU2fSign, options->relying_party_id,
+        options->challenge, /*is_cross_origin=*/false);
+  } else if (payment) {
+    auto* web_contents = WebContents::FromRenderFrameHost(GetRenderFrameHost());
+    if (!web_contents) {
+      CompleteGetAssertionRequest(
+          blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
+      return;
+    }
+    url::Origin top_origin =
+        url::Origin::Create(web_contents->GetLastCommittedURL());
+    client_data_json_ = BuildClientDataJson(
+        ClientDataRequestType::kPaymentGet, caller_origin_.Serialize(),
+        options->challenge, is_cross_origin, std::move(payment),
+        relying_party_id_, top_origin.Serialize());
+  } else {
+    client_data_json_ = BuildClientDataJson(
+        ClientDataRequestType::kWebAuthnGet, caller_origin_.Serialize(),
+        options->challenge, is_cross_origin);
+  }
+
+  // Cryptotoken requests should be proxied without UI.
+  if (origin_is_crypto_token_extension || disable_ui_) {
+    DCHECK(!options->is_conditional);
+    request_delegate_->DisableUI();
+  }
+
+  request_delegate_->SetConditionalRequest(options->is_conditional);
+
+  if (options->allow_credentials.empty()) {
+    if (!GetWebAuthenticationDelegate()->SupportsResidentKeys(
+            GetRenderFrameHost())) {
+      CompleteGetAssertionRequest(
+          blink::mojom::AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED);
+      return;
+    }
+    empty_allow_list_ = true;
+  }
+
+  if (options->appid) {
+    requested_extensions_.insert(RequestExtension::kAppID);
+    app_id_ = ProcessAppIdExtension(*options->appid, caller_origin_);
+    if (!app_id_) {
+      CompleteGetAssertionRequest(
+          blink::mojom::AuthenticatorStatus::INVALID_DOMAIN);
+      return;
+    }
+  }
+
+  if (options->large_blob_read && options->large_blob_write) {
+    CompleteGetAssertionRequest(
+        blink::mojom::AuthenticatorStatus::CANNOT_READ_AND_WRITE_LARGE_BLOB);
+    return;
+  }
+
+  if (options->large_blob_read) {
+    requested_extensions_.insert(RequestExtension::kLargeBlobRead);
+  } else if (options->large_blob_write) {
+    if (options->allow_credentials.size() != 1) {
+      CompleteGetAssertionRequest(blink::mojom::AuthenticatorStatus::
+                                      INVALID_ALLOW_CREDENTIALS_FOR_LARGE_BLOB);
+      return;
+    }
+    requested_extensions_.insert(RequestExtension::kLargeBlobWrite);
+  }
+
+  timer_->Start(
+      FROM_HERE, AdjustTimeout(options->timeout, GetRenderFrameHost()),
+      base::BindOnce(&AuthenticatorCommonTizen::OnTimeout, base::Unretained(this)));
+
+
+  bool is_first = true;
+  absl::optional<std::vector<uint8_t>> last_id;
+  if (options->prf) {
+    requested_extensions_.insert(RequestExtension::kPRF);
+    for (const auto& prf_input_from_renderer : options->prf_inputs) {
+      device::CtapGetAssertionOptions::PRFInput prf_input;
+
+      // This statement enforces invariants that should be established by the
+      // renderer.
+      if (
+          // Only the first element in the vector may be the default.
+          (!is_first && !prf_input_from_renderer->id) ||
+          // The PRF inputs must be sorted by credential ID to show that there
+          // are no duplicates.
+          (last_id.has_value() && prf_input_from_renderer->id.has_value() &&
+           *last_id >= *prf_input_from_renderer->id) ||
+          // The lengths are specified in authenticator.mojom, so hopefully Mojo
+          // enforces them too.
+          prf_input_from_renderer->first.size() != prf_input.salt1.size() ||
+          (prf_input_from_renderer->second &&
+           prf_input_from_renderer->second->size() != prf_input.salt1.size())) {
+        NOTREACHED();
+
+        CompleteGetAssertionRequest(
+            blink::mojom::AuthenticatorStatus::UNKNOWN_ERROR);
+        return;
+      }
+      is_first = false;
+      last_id = prf_input_from_renderer->id;
+
+      if (prf_input_from_renderer->id) {
+        prf_input.credential_id = std::move(*prf_input_from_renderer->id);
+      }
+
+      memcpy(prf_input.salt1.data(), prf_input_from_renderer->first.data(),
+             prf_input.salt1.size());
+      if (prf_input_from_renderer->second) {
+        prf_input.salt2.emplace();
+        memcpy(prf_input.salt2->data(), prf_input_from_renderer->second->data(),
+               prf_input.salt2->size());
+      }
+    }
+  }
+
+  if (options->large_blob_write) {
+    data_decoder_.GzipCompress(
+        *options->large_blob_write,
+        base::BindOnce(&AuthenticatorCommonTizen::OnLargeBlobCompressed,
+                       weak_factory_.GetWeakPtr()));
+    return;
+  }
+
+  ga_options_.attestation_formats =
+      num_attestation_formats_ ? &device_attestation_formats_ : nullptr;
+
+  PopulateGAWebauthnArgs(std::move(options));
+  int ret =
+      wauthn_get_assertion(&ga_client_data_, &ga_options_, &ga_callbacks_);
+  if(ret != WAUTHN_ERROR_NONE)
+    Cancel();
+}
+
+void AuthenticatorCommonTizen::IsUserVerifyingPlatformAuthenticatorAvailable(
+    blink::mojom::Authenticator::
+        IsUserVerifyingPlatformAuthenticatorAvailableCallback callback) {
+  // Check for a delegate override. Chrome overrides IsUVPAA() in Guest mode
+  // and, on Windows only, in Incognito.
+  absl::optional<bool> is_uvpaa_override =
+      GetWebAuthenticationDelegate()
+          ->IsUserVerifyingPlatformAuthenticatorAvailableOverride(
+              GetRenderFrameHost());
+  if (is_uvpaa_override) {
+    std::move(callback).Run(*is_uvpaa_override);
+    return;
+  }
+
+  // Record IsUVPAA result in a UMA metric, but only if they're not the
+  // WebAuthenticationDelegate override value, so that results from the testing
+  // API and disabling in Guest/Off-The-Record profiles aren't counted.
+  auto uma_decorated_callback =
+      base::BindOnce([](bool available) {
+        base::UmaHistogramBoolean(
+            "WebAuthentication.IsUVPlatformAuthenticatorAvailable2", available);
+        return available;
+      }).Then(std::move(callback));
+
+#if defined(OS_MAC)
+  IsUVPlatformAuthenticatorAvailable(GetBrowserContext(),
+                                     std::move(uma_decorated_callback));
+#elif defined(OS_WIN)
+  IsUVPlatformAuthenticatorAvailable(std::move(uma_decorated_callback));
+#elif BUILDFLAG(IS_CHROMEOS_ASH)
+  IsUVPlatformAuthenticatorAvailable(std::move(uma_decorated_callback));
+#else
+  std::move(uma_decorated_callback).Run(false);
+#endif
+}
+
+void AuthenticatorCommonTizen::Cancel() {
+  // Invoke webauthn cancel
+    wauthn_cancel();
+  CancelWithStatus(blink::mojom::AuthenticatorStatus::ABORT_ERROR);
+}
+
+void AuthenticatorCommonTizen::SignalFailureToRequestDelegate(
+    const ::device::FidoAuthenticator* authenticator,
+    AuthenticatorRequestClientDelegate::InterestingFailureReason reason,
+    blink::mojom::AuthenticatorStatus status) {
+  error_awaiting_user_acknowledgement_ = status;
+
+  // The request has failed, but the UI may delay resolution of the request
+  // callback and cleanup of the FidoRequestHandler and its associated
+  // discoveries and authenticators. Tell them to stop processing the request in
+  // the meantime.
+  request_->StopDiscoveries();
+  request_->CancelActiveAuthenticators();
+
+  // If WebAuthnUi is enabled, this error blocks until after receiving user
+  // acknowledgement. Otherwise, the error is returned right away.
+  if (request_delegate_->DoesBlockRequestOnFailure(reason)) {
+    return;
+  }
+  CancelWithStatus(error_awaiting_user_acknowledgement_);
+}  // namespace content
+
+// TODO(crbug.com/814418): Add web tests to verify timeouts are
+// indistinguishable from NOT_ALLOWED_ERROR cases.
+void AuthenticatorCommonTizen::OnTimeout() {
+  DCHECK(request_delegate_);
+  if (awaiting_attestation_response_) {
+    awaiting_attestation_response_ = false;
+  }
+
+  SignalFailureToRequestDelegate(
+      /*authenticator=*/nullptr,
+      AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout,
+      blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
+}
+
+void AuthenticatorCommonTizen::CancelWithStatus(
+    blink::mojom::AuthenticatorStatus status) {
+  DCHECK(!make_credential_response_callback_ ||
+         !get_assertion_response_callback_);
+  if (make_credential_response_callback_) {
+    CompleteMakeCredentialRequest(status);
+  } else if (get_assertion_response_callback_) {
+    CompleteGetAssertionRequest(status);
+  }
+}
+
+void AuthenticatorCommonTizen::OnCancelFromUI() {
+  CancelWithStatus(error_awaiting_user_acknowledgement_);
+}
+
+blink::mojom::MakeCredentialAuthenticatorResponsePtr
+AuthenticatorCommonTizen::CreateMakeCredentialResponse(
+ const wauthn_pubkey_credential_attestation_s* pubkey_cred,
+    AttestationErasureOption attestation_erasure) {
+  auto response = blink::mojom::MakeCredentialAuthenticatorResponse::New();
+  auto common_info = blink::mojom::CommonCredentialInfo::New();
+common_info->client_data_json =
+      ToBuffer(*pubkey_cred->response->client_data_json);
+  common_info->raw_id = ToBuffer(*pubkey_cred->rawId);
+  common_info->id = Base64UrlEncode(common_info->raw_id);
+  base::flat_set<device::FidoTransportProtocol> transports;
+  if (!pubkey_cred->response->transports) {
+    transports.insert(device::FidoTransportProtocol::kMaxValue);
+  }
+
+  if (pubkey_cred->response->transports & 1) {
+    transports.insert(device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
+  }
+  if (pubkey_cred->response->transports & 2) {
+    transports.insert(device::FidoTransportProtocol::kNearFieldCommunication);
+  }
+  if (pubkey_cred->response->transports & 4) {
+    transports.insert(device::FidoTransportProtocol::kBluetoothLowEnergy);
+  }
+  if (pubkey_cred->response->transports & 8) {
+    transports.insert(device::FidoTransportProtocol::kAndroidAccessory);
+  }
+  // if (pubkey_cred->response->transports & 16) {      Need to check
+  //   transports.insert(device::FidoTransportProtocol::kHybrid);
+  // }
+  if (pubkey_cred->response->transports & 32) {
+    transports.insert(device::FidoTransportProtocol::kInternal);
+  }
+    response->transports.assign(transports.begin(), transports.end());
+
+
+  response->attestation_object =
+      ToBuffer(*pubkey_cred->response->attestation_object);
+  common_info->authenticator_data =
+      ToBuffer(*pubkey_cred->response->authenticator_data);
+  if (pubkey_cred->response->subject_pubkey_info) {
+    response->public_key_der =
+        ToBuffer(*pubkey_cred->response->subject_pubkey_info);
+  }
+  response->info = std::move(common_info);
+
+  response->public_key_algo = pubkey_cred->response->pubkey_alg;
+
+  return response;
+}
+
+void AuthenticatorCommonTizen::CompleteMakeCredentialRequest(
+    blink::mojom::AuthenticatorStatus status,
+    blink::mojom::MakeCredentialAuthenticatorResponsePtr response,
+    Focus check_focus) {
+  DCHECK(make_credential_response_callback_);
+  if (check_focus != Focus::kDontCheck && !(request_delegate_ && IsFocused())) {
+    std::move(make_credential_response_callback_)
+        .Run(blink::mojom::AuthenticatorStatus::NOT_FOCUSED, nullptr);
+  } else {
+    std::move(make_credential_response_callback_)
+        .Run(status, std::move(response));
+  }
+
+  Cleanup();
+}
+
+blink::mojom::GetAssertionAuthenticatorResponsePtr
+AuthenticatorCommonTizen::CreateGetAssertionResponse(
+ const wauthn_pubkey_credential_assertion_s* pubkey_cred,
+    absl::optional<std::vector<uint8_t>> large_blob) {
+  auto response = blink::mojom::GetAssertionAuthenticatorResponse::New();
+  auto common_info = blink::mojom::CommonCredentialInfo::New();
+
+  common_info->client_data_json =
+      ToBuffer(*pubkey_cred->response->client_data_json);
+  common_info->raw_id = ToBuffer(*pubkey_cred->rawId);
+  common_info->id = Base64UrlEncode(common_info->raw_id);
+  response->info = std::move(common_info);
+  response->info->authenticator_data =
+      ToBuffer(*(pubkey_cred->response->authenticator_data));
+  response->signature = ToBuffer(*pubkey_cred->response->signature);
+
+  if (pubkey_cred->response->user_handle) {
+    pubkey_cred->response->user_handle->size
+        ? response->user_handle.emplace(
+              ToBuffer(*pubkey_cred->response->user_handle))
+        : response->user_handle.emplace();
+  }
+  return response;
+}
+
+void AuthenticatorCommonTizen::CompleteGetAssertionRequest(
+    blink::mojom::AuthenticatorStatus status,
+    blink::mojom::GetAssertionAuthenticatorResponsePtr response) {
+  DCHECK(get_assertion_response_callback_);
+  std::move(get_assertion_response_callback_).Run(status, std::move(response));
+  Cleanup();
+}
+
+void AuthenticatorCommonTizen::Cleanup() {
+  if (awaiting_attestation_response_) {
+    awaiting_attestation_response_ = false;
+  }
+
+  timer_->Stop();
+  request_.reset();
+  discovery_factory_.reset();
+  discovery_factory_testing_override_ = nullptr;
+  request_delegate_.reset();
+  make_credential_response_callback_.Reset();
+  get_assertion_response_callback_.Reset();
+  client_data_json_.clear();
+  app_id_.reset();
+  caller_origin_ = url::Origin();
+  relying_party_id_.clear();
+  empty_allow_list_ = false;
+  error_awaiting_user_acknowledgement_ =
+      blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+  requested_extensions_.clear();
+}
+
+void AuthenticatorCommonTizen::DisableUI() {
+  disable_ui_ = true;
+}
+
+RenderFrameHost* AuthenticatorCommonTizen::GetRenderFrameHost() const {
+  RenderFrameHost* ret = RenderFrameHost::FromID(render_frame_host_id_);
+  DCHECK(ret);
+  return ret;
+}
+
+BrowserContext* AuthenticatorCommonTizen::GetBrowserContext() const {
+  return GetRenderFrameHost()->GetBrowserContext();
+}
+
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.h b/tizen_src/chromium_impl/content/browser/webauthn/authenticator_common_tizen.h
new file mode 100644 (file)
index 0000000..29b8317
--- /dev/null
@@ -0,0 +1,321 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_TIZEN_H_
+#define CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_TIZEN_H_
+
+#include <stdint.h>
+#include <webauthn.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/authenticator_request_client_delegate.h"
+#include "content/public/browser/global_routing_id.h"
+#include "services/data_decoder/public/cpp/data_decoder.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
+#include "url/origin.h"
+
+namespace base {
+class OneShotTimer;
+}
+
+namespace device {
+
+class FidoRequestHandlerBase;
+class FidoDiscoveryFactory;
+
+enum class FidoReturnCode : uint8_t;
+
+enum class GetAssertionStatus;
+enum class MakeCredentialStatus;
+
+}  // namespace device
+
+namespace url {
+class Origin;
+}
+
+namespace content {
+
+class BrowserContext;
+class RenderFrameHost;
+class WebAuthRequestSecurityChecker;
+
+enum class RequestExtension;
+enum class AttestationErasureOption;
+
+// Common code for any WebAuthn Authenticator interfaces.
+class CONTENT_EXPORT AuthenticatorCommonTizen {
+ public:
+  // Creates a new AuthenticatorCommonTizen. Callers must ensure that this instance
+  // outlives the RenderFrameHost.
+  explicit AuthenticatorCommonTizen(RenderFrameHost* render_frame_host);
+  virtual ~AuthenticatorCommonTizen();
+
+  // This is not-quite an implementation of blink::mojom::Authenticator. The
+  // first two functions take the caller's origin explicitly. This allows the
+  // caller origin to be overridden if needed. `GetAssertion()` also takes the
+  // optional `payment` to add to "clientDataJson" after the browser displays
+  // the payment confirmation dialog to the user.
+  void MakeCredential(
+      url::Origin caller_origin,
+      blink::mojom::PublicKeyCredentialCreationOptionsPtr options,
+      blink::mojom::Authenticator::MakeCredentialCallback callback);
+  void GetAssertion(url::Origin caller_origin,
+                    blink::mojom::PublicKeyCredentialRequestOptionsPtr options,
+                    blink::mojom::PaymentOptionsPtr payment,
+                    blink::mojom::Authenticator::GetAssertionCallback callback);
+  void IsUserVerifyingPlatformAuthenticatorAvailable(
+      blink::mojom::Authenticator::
+          IsUserVerifyingPlatformAuthenticatorAvailableCallback callback);
+  void Cancel();
+
+  void Cleanup();
+
+  void DisableUI();
+
+  // GetRenderFrameHost returns a pointer to the RenderFrameHost that was given
+  // to the constructor. Use this rather than keeping a copy of the
+  // RenderFrameHost* that was passed in.
+  //
+  // This object assumes that the RenderFrameHost overlives it but, in case it
+  // doesn't, this avoids holding a raw pointer and creating a use-after-free.
+  // If the RenderFrameHost has been destroyed then this function will return
+  // nullptr and the process will crash when it tries to use it.
+  RenderFrameHost* GetRenderFrameHost() const;
+
+ protected:
+  // MaybeCreateRequestDelegate returns the embedder-provided implementation of
+  // AuthenticatorRequestClientDelegate, which encapsulates per-request state
+  // relevant to the embedder, e.g. because it is used to display browser UI.
+  //
+  // Chrome may return nullptr here in order to ensure that at most one request
+  // per WebContents is ongoing at once.
+  virtual std::unique_ptr<AuthenticatorRequestClientDelegate>
+  MaybeCreateRequestDelegate();
+
+  std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
+
+ private:
+
+
+  // Enumerates whether or not to check that the WebContents has focus.
+  enum class Focus {
+    kDoCheck,
+    kDontCheck,
+  };
+
+  // Replaces the current |request_| with a |MakeCredentialRequestHandler|,
+  // effectively restarting the request.
+  void StartMakeCredentialRequest(bool allow_skipping_pin_touch);
+
+  // Replaces the current |request_| with a |GetAssertionRequestHandler|,
+  // effectively restarting the request.
+  void StartGetAssertionRequest(bool allow_skipping_pin_touch);
+
+  bool IsFocused() const;
+
+  // Callback to handle the large blob being compressed before attempting to
+  // start a request.
+  void OnLargeBlobCompressed(
+      data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result);
+
+  // Callback to handle the large blob being uncompressed before completing a
+  // request.
+  void OnLargeBlobUncompressed(
+      device::AuthenticatorGetAssertionResponse response,
+      data_decoder::DataDecoder::ResultOrError<mojo_base::BigBuffer> result);
+
+  // Runs when timer expires and cancels all issued requests to a U2fDevice.
+  void OnTimeout();
+  // Cancels the currently pending request (if any) with the supplied status.
+  void CancelWithStatus(blink::mojom::AuthenticatorStatus status);
+  // Runs when the user cancels WebAuthN request via UI dialog.
+  void OnCancelFromUI();
+
+
+  // Signals to the request delegate that the request has failed for |reason|.
+  // The request delegate decides whether to present the user with a visual
+  // error before the request is finally resolved with |status|.
+  void SignalFailureToRequestDelegate(
+      const device::FidoAuthenticator* authenticator,
+      AuthenticatorRequestClientDelegate::InterestingFailureReason reason,
+      blink::mojom::AuthenticatorStatus status);
+
+  // Creates a make credential response
+  blink::mojom::MakeCredentialAuthenticatorResponsePtr
+  CreateMakeCredentialResponse(
+      const wauthn_pubkey_credential_attestation_s* pubkey_cred,
+      AttestationErasureOption attestation_erasure);
+
+  // Runs |make_credential_response_callback_| and then Cleanup().
+  void CompleteMakeCredentialRequest(
+      blink::mojom::AuthenticatorStatus status,
+      blink::mojom::MakeCredentialAuthenticatorResponsePtr response = nullptr,
+      Focus focus_check = Focus::kDontCheck);
+
+  // Creates a get assertion response.
+  blink::mojom::GetAssertionAuthenticatorResponsePtr CreateGetAssertionResponse(
+      const wauthn_pubkey_credential_assertion_s* pubkey_cred,
+      absl::optional<std::vector<uint8_t>> large_blob = absl::nullopt);
+
+  // Runs |get_assertion_response_callback_| and then Cleanup().
+  void CompleteGetAssertionRequest(
+      blink::mojom::AuthenticatorStatus status,
+      blink::mojom::GetAssertionAuthenticatorResponsePtr response = nullptr);
+
+  BrowserContext* GetBrowserContext() const;
+  // Webauthn:
+  void PopulateMCWebauthnArgs(
+      blink::mojom::PublicKeyCredentialCreationOptionsPtr options);
+  void PopulateGAWebauthnArgs(
+      blink::mojom::PublicKeyCredentialRequestOptionsPtr options);
+  static void DisplayQRCallback(const char* qr_contents, void* data);
+  static void MCCallback(
+      const wauthn_pubkey_credential_attestation_s* pubkey_cred,
+      wauthn_error_e result,
+      void* data);
+  static void GACallback(
+      const wauthn_pubkey_credential_assertion_s* pubkey_cred,
+      wauthn_error_e result,
+      void* data);
+  static void MCUpdateLinkedDataCallback(
+      const wauthn_hybrid_linked_data_s* linked_data,
+      wauthn_error_e result,
+      void* data);
+  static void GAUpdateLinkedDataCallback(
+      const wauthn_hybrid_linked_data_s* linked_data,
+      wauthn_error_e result,
+      void* data);
+
+  const GlobalRenderFrameHostId render_frame_host_id_;
+  std::unique_ptr<device::FidoRequestHandlerBase> request_;
+  std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory_;
+  device::FidoDiscoveryFactory* discovery_factory_testing_override_ = nullptr;
+  blink::mojom::Authenticator::MakeCredentialCallback
+      make_credential_response_callback_;
+  blink::mojom::Authenticator::GetAssertionCallback
+      get_assertion_response_callback_;
+  std::string client_data_json_;
+  // empty_allow_list_ is true iff a GetAssertion is currently pending and the
+  // request did not list any credential IDs in the allow list.
+  bool empty_allow_list_ = false;
+  bool disable_ui_ = false;
+  url::Origin caller_origin_;
+  std::string relying_party_id_;
+  scoped_refptr<WebAuthRequestSecurityChecker> security_checker_;
+
+  wauthn_client_data_s mc_client_data_ = {0};
+  wauthn_client_data_s ga_client_data_ = {0};
+  wauthn_pubkey_cred_creation_options_s mc_options_ = {0};
+  wauthn_pubkey_cred_request_options_s ga_options_ = {0};
+  wauthn_mc_callbacks_s mc_callbacks_ = {0};
+  wauthn_ga_callbacks_s ga_callbacks_ = {0};
+
+  // Data members for mc_client_data
+  std::vector<unsigned char> client_data_vector_;
+  wauthn_const_buffer_s client_data_json_buff_;
+  const std::string extension_id_[17] = {"appid",          // 0
+                                         "txAuthSimple",   // 1
+                                         "txAuthGeneric",  // 2
+                                         "authnSel",       // 3
+                                         "exts",           // 4
+                                         "uvi",            // 5
+                                         "loc",            // 6
+                                         "uvm",            // 7
+                                         "credProtect",    // 8
+                                         "credBlob",       // 9
+                                         "largeBlobKey",   // 10
+                                         "minPinLength",   // 11
+                                         "hmac-secret",    // 12
+                                         "appidExclude",   // 13
+                                         "credProps",      // 14
+                                         "largeBlob",      // 15
+                                         "payment"};       // 16
+  std::vector<std::string> extension_value_;
+  // Data members for mc_options
+  wauthn_rp_entity_s rp_ = {0};
+  wauthn_user_entity_s user_ = {0};
+  wauthn_pubkey_cred_params_s pubkey_cred_params_ = {0};
+  wauthn_pubkey_cred_descriptors_s excluded_credentials_ = {0};
+  wauthn_attestation_formats_s mc_attestation_formats_ = {0};
+  wauthn_authentication_exts_s mc_extensions_ = {0};
+  wauthn_authenticator_sel_cri_s mc_authenticator_selection_criteria_ = {
+    WAUTHN_AUTHENTICATOR_ATTACHMENT_NONE, WAUTHN_RESIDENT_KEY_REQUIREMENT_NONE,false,WAUTHN_USER_VERIFICATION_REQUIREMENT_NONE
+  };
+  // mc_options.rp
+  std::string rel_party_id_;
+  std::string rel_party_name_;
+
+  // mc_options.user
+  wauthn_const_buffer_s user_id_buff_ = {0};
+  std::vector<uint8_t> user_id_vector_;
+  std::string user_name_string_;
+  std::string user_display_name_string_;
+
+  // mc_options.pubkey_cred_params
+  std::vector<wauthn_pubkey_cred_param_s> params_vector_;
+
+  // mc_options.exclude_credentials
+  std::vector<wauthn_pubkey_cred_descriptor_s> excluded_creds_vector_;
+  std::vector<std::vector<uint8_t>> excluded_creds_id_int8_vector_;
+  std::vector<wauthn_const_buffer_s> excluded_creds_id_buffer_vector_;
+
+  // mc_options.attestation_formats
+  std::vector<std::string> mc_attestation_formats_string_vector_;
+  std::vector<wauthn_const_buffer_s> mc_attestation_formats_vector_;
+
+  // mc_options_.extensions
+  std::vector<wauthn_const_buffer_s> mc_extension_id_buffer_vector_;
+  std::vector<wauthn_const_buffer_s> mc_extension_value_buffer_vector_;
+  std::vector<wauthn_authentication_ext_s> mc_extensions_vector_;
+
+  // Data members for GA
+  std::string rp_id_string_;
+  std::vector<wauthn_pubkey_cred_descriptor_s> pubkey_cred_descriptor_vector_;
+  std::vector<std::vector<uint8_t>> pubkey_cred_id_int8_vector_;
+  std::vector<wauthn_const_buffer_s> pubkey_cred_id_buffer_vector_;
+  wauthn_pubkey_cred_descriptors_s pubkey_cred_descriptors_ = {0};
+
+  wauthn_attestation_pref_e device_attestation_ = WAUTHN_ATTESTATION_PREF_NONE;
+  int num_attestation_formats_ = 0;
+
+  std::vector<std::string> ga_attestation_formats_string_vector_;
+  std::vector<wauthn_const_buffer_s> ga_attestation_formats_vector_;
+  wauthn_attestation_formats_s device_attestation_formats_ = {0};
+  wauthn_authentication_exts_s ga_extensions_ = {0};
+  std::vector<wauthn_const_buffer_s> ga_extension_id_buffer_vector_;
+  std::vector<wauthn_const_buffer_s> ga_extension_value_buffer_vector_;
+  std::vector<wauthn_authentication_ext_s> ga_extensions_vector_;
+
+  wauthn_ga_callbacks_s gaCallbacks;
+  std::unique_ptr<base::OneShotTimer> timer_ =
+      std::make_unique<base::OneShotTimer>();
+  absl::optional<std::string> app_id_;
+  // awaiting_attestation_response_ is true if the embedder has been queried
+  // about an attestsation decision and the response is still pending.
+  bool awaiting_attestation_response_ = false;
+  blink::mojom::AuthenticatorStatus error_awaiting_user_acknowledgement_ =
+      blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR;
+  data_decoder::DataDecoder data_decoder_;
+
+  base::flat_set<RequestExtension> requested_extensions_;
+
+  base::WeakPtrFactory<AuthenticatorCommonTizen> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(AuthenticatorCommonTizen);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEBAUTH_AUTHENTICATOR_COMMON_H_
index 740d302fdf562a070b5e17a23d8b661dea293014..62777240b843d5aacb8aa85ae37eb814ab64845d 100644 (file)
@@ -705,6 +705,15 @@ void EWebView::RunPendingSetFocus(Eina_Bool focus) {
 }
 #endif
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+void EWebView::CancelAuthentication() {
+  if (!rwhv()) {
+    return;
+  }
+  rwhv()->CancelAuthentication();
+}
+#endif
+
 void EWebView::SetFocus(Eina_Bool focus) {
   if (!web_contents_ || !rwhv() || (HasFocus() == focus))
     return;
index 9786c5f3f74623dcd18719811a75bfded83853c9..6f621c0304c57c3459a55c37b3c355e8c710c846 100644 (file)
@@ -522,6 +522,10 @@ class EWebView {
 
   void RenderViewReady();
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  void CancelAuthentication();
+#endif
+
   /**
    * Creates a snapshot of given rectangle from EWebView
    *
@@ -915,6 +919,7 @@ class EWebView {
 #endif
 #endif
 
+
   void SetScriptsCanOpenWindows(bool);
   bool GetScriptsCanOpenWindows() const;
 
index 0ee91d9cf23545be4493b3b9271c964d530b501b..0bca754192261f6c7e14ffb979bcb1894b8931c5 100644 (file)
@@ -204,6 +204,8 @@ enum CallbackType {
   DidNotAllowScript,
   FocusIn,
   FocusOut,
+  DisplayQRCode,
+  CloseQRCode,
   FormRepostWarningShow,
   BeforeFormRepostWarningShow,
   NotificationPermissionReply
@@ -328,6 +330,8 @@ DECLARE_EWK_VIEW_CALLBACK(EdgeScrollBottom, "edge,scroll,bottom", bool*);
 DECLARE_EWK_VIEW_CALLBACK(EdgeScrollLeft, "edge,scroll,left", bool*);
 DECLARE_EWK_VIEW_CALLBACK(EdgeScrollRight, "edge,scroll,right", bool*);
 DECLARE_EWK_VIEW_CALLBACK(EdgeScrollTop, "edge,scroll,top", bool*);
+DECLARE_EWK_VIEW_CALLBACK(DisplayQRCode, "webauth,display,qr", const char*);
+DECLARE_EWK_VIEW_CALLBACK(CloseQRCode, "webauth,response", void);
 #if defined(OS_TIZEN_TV_PRODUCT)
 DECLARE_EWK_VIEW_CALLBACK(ContextMenuShow,
                           "contextmenu,show",
index 659c806f471a4bec1f5fa48a2a947a3c44cbaee4..7f9f1be4a91568803a97442b5bcb63d22a8d1dca 100644 (file)
@@ -2085,4 +2085,12 @@ Eina_Bool ewk_view_mouse_pointer_support_get(const Evas_Object *view)
 #endif
 }
 
+void ewk_view_webauthn_cancel(const Evas_Object* view) {
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+  impl->CancelAuthentication();
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen");
+#endif
+}
 /* LCOV_EXCL_STOP */
index fc067eff03a5d681df9eeba7205087920e43b4f6..ec77cab9f13eabe24fb8d5debb68f92aee0c2727 100644 (file)
@@ -1584,6 +1584,14 @@ EXPORT_API Eina_Bool ewk_view_mouse_pointer_support_set(Evas_Object *view, Eina_
  */
 EXPORT_API Eina_Bool ewk_view_mouse_pointer_support_get(const Evas_Object *view);
 
+/**
+ * @brief Cancels the authentication process of webauthn.
+ *
+ * @since_tizen 9.0
+ *
+ * @param[in] o The view object.
+ */
+EXPORT_API void ewk_view_webauthn_cancel(const Evas_Object* o);
 
 #ifdef __cplusplus
 }
index 63e9e68dab674fa289ebf6c937f71c6f2424a6bb..96bcb389cc356acf449e5f6c268c20905a70084a 100644 (file)
@@ -1616,4 +1616,21 @@ void WebContentsDelegateEfl::OnIsVideoPlayingGet(bool is_playing,
 void WebContentsDelegateEfl::ShowRepostFormWarningDialog(WebContents* source) {
   _Ewk_Form_Repost_Decision_Request::Create(source);
 }
+
+void WebContentsDelegateEfl::DisplayQRCode(std::string contents) {
+  if (!web_view_) {
+    LOG(INFO) << "QR WebContentsDelegateEfl fail";
+    return;
+  }
+  web_view_->SmartCallback<EWebViewCallbacks::DisplayQRCode>().call(
+      contents.c_str());
+}
+
+void WebContentsDelegateEfl::CloseQRCode() {
+  if (!web_view_) {
+    return;
+  }
+  web_view_->SmartCallback<EWebViewCallbacks::CloseQRCode>().call();
+}
+
 }  // namespace content
index fcab5dec62cf86f4efb187e99c44639921b1a0ab..d123cce18208f97c101934a5e9ca80fd5b7c8bd6 100644 (file)
@@ -132,6 +132,8 @@ class WebContentsDelegateEfl : public WebContentsDelegate,
   // Browser edge scroll
   void DidEdgeScrollBy(const gfx::Point& offset, bool handled) override;
   void UpdateTooltipUnderCursor(const std::u16string& text) override;
+  void DisplayQRCode(std::string contents) override;
+  void CloseQRCode() override;
 
 #if defined(TIZEN_TBM_SUPPORT)
   bool OffscreenRenderingEnabled() override;
index a0482dbe2dcbf46c0d9fad0f561cee17ba8b0ca7..375ad4730afba2ee577d762241e3ef187473a8e8 100644 (file)
@@ -73,4 +73,8 @@ executable("ubrowser") {
       configs += [ "//tizen_src/build:libvd-win-util" ]
     }
   }
+  if (tizen_passkey_support) {
+      configs += [ "//tizen_src/build:capi-media-vision-barcode" ]
+      configs += [ "//tizen_src/build:libcapi-media-vision-barcode" ]
+  }
 }
index 18f121d3193bf7b631db3fa9968b40915950e7fc..13722af6b2ebc74b1738a51dbe3958b62c540a61 100644 (file)
 
 #include "tizen/system_info.h"
 
+#if defined(TIZEN_PASSKEY_SUPPORT)
+#include <mv_barcode.h>
+#endif
+
 #if defined(OS_TIZEN)
 #include <efl_extension.h>
 #endif
@@ -168,6 +172,10 @@ Window::Window(Browser& browser, int width, int height, bool incognito)
                                  &Window::OnFormRepostWarningShow, this);
   evas_object_smart_callback_add(web_view_, "before,repost,warning,show",
                                  &Window::OnBeforeFormRepostWarningShow, this);
+  evas_object_smart_callback_add(web_view_, "webauth,display,qr",
+                                 &Window::DisplayQRCode, this);
+  evas_object_smart_callback_add(web_view_, "webauth,response",
+                                 &Window::CloseQRCode, this);
 
 #if defined(OS_TIZEN)
   if (IsTvProfile()) {
@@ -587,6 +595,96 @@ void Window::OnBeforeFormRepostWarningShow(void* data,
   thiz->ui_->ClosePopup();
 }
 
+void Window::DisplayQRCode(void* data, Evas_Object*, void* contents) {
+  log_trace("%s", __PRETTY_FUNCTION__);
+
+  const char* path = "/tmp/webauthn-qrcode.png";
+#if defined(TIZEN_PASSKEY_SUPPORT)
+  const char* qr_contents = (const char*)contents;
+  int ret;
+  int width = 300;
+  int height = 300;
+  int qr_version = 5;
+  mv_engine_config_h engine_cfg = NULL;
+  mv_barcode_type_e type = MV_BARCODE_QR;
+  mv_barcode_qr_mode_e qr_enc_mode = MV_BARCODE_QR_MODE_UTF8;
+  mv_barcode_qr_ecc_e qr_ecc = MV_BARCODE_QR_ECC_LOW;
+  mv_barcode_image_format_e image_format = MV_BARCODE_IMAGE_FORMAT_PNG;
+
+  ret = mv_barcode_generate_image(engine_cfg, qr_contents, width, height, type,
+                                  qr_enc_mode, qr_ecc, qr_version, path,
+                                  image_format);
+
+  if (ret != MEDIA_VISION_ERROR_NONE) {
+    log_info("mv_barcode_generate_image failed with code %d", ret);
+    return;
+  }
+#endif
+
+  Window* thiz = static_cast<Window*>(data);
+
+  thiz->layout_ = elm_layout_add(thiz->window_);
+
+  if (!thiz->layout_) {
+    log_info("no layout!");
+    return;
+  }
+
+  elm_layout_theme_set(thiz->layout_, "layout", "application", "default");
+  evas_object_size_hint_weight_set(thiz->layout_, EVAS_HINT_EXPAND,
+                                   EVAS_HINT_EXPAND);
+  evas_object_show(thiz->layout_);
+
+  thiz->qr_window_ = elm_popup_add(thiz->layout_);
+
+  if (!thiz->qr_window_) {
+    return;
+  }
+
+  evas_object_move(thiz->qr_window_, 350, 300);
+  evas_object_resize(thiz->qr_window_, 600, 600);
+  evas_object_show(thiz->qr_window_);
+
+  Evas_Object* cancel_btn = elm_button_add(thiz->qr_window_);
+  elm_object_text_set(cancel_btn, "Cancel");
+  elm_object_style_set(cancel_btn, "bottom");
+  evas_object_resize(cancel_btn, 100, 30);
+  evas_object_move(cancel_btn, 800, 150);
+  evas_object_show(cancel_btn);
+  elm_object_part_content_set(thiz->layout_, "button1", cancel_btn);
+  evas_object_smart_callback_add(cancel_btn, "clicked", CancelAuthentication,
+                                 thiz);
+
+  Evas* e = evas_object_evas_get(thiz->qr_window_);
+  thiz->qr_img_ = evas_object_image_add(e);
+  evas_object_image_file_set(thiz->qr_img_, path, NULL);
+  evas_object_image_fill_set(thiz->qr_img_, 0, 0, 600, 600);
+  evas_object_move(thiz->qr_img_, 350, 300);
+  evas_object_resize(thiz->qr_img_, 600, 600);
+  evas_object_show(thiz->qr_img_);
+}
+
+void Window::CloseQRCode(void* data, Evas_Object*, void*) {
+  Window* thiz = static_cast<Window*>(data);
+  evas_object_del(thiz->qr_img_);
+  evas_object_del(thiz->qr_window_);
+  evas_object_del(thiz->layout_);
+  thiz->qr_img_ = NULL;
+  thiz->qr_window_ = NULL;
+  thiz->layout_ = NULL;
+}
+
+void Window::CancelAuthentication(void* data, Evas_Object*, void*) {
+  Window* thiz = static_cast<Window*>(data);
+  ewk_view_webauthn_cancel(thiz->web_view_);
+  evas_object_del(thiz->qr_img_);
+  evas_object_del(thiz->qr_window_);
+  evas_object_del(thiz->layout_);
+  thiz->qr_img_ = NULL;
+  thiz->qr_window_ = NULL;
+  thiz->layout_ = NULL;
+}
+
 void Window::OnUserFormRepostDecisionTaken(bool decision, void* data) {
   log_trace("%s", __PRETTY_FUNCTION__);
   Ewk_Form_Repost_Decision_Request* request =
index 763467fd5df5bb7d646f7b51966a354c8d825d57..e076c5ee32de68b43015997b173fd06197d949de 100644 (file)
@@ -79,6 +79,9 @@ class Window {
   static void OnHostFocusedIn(void* data, Evas_Object*, void*);
   static void OnHostFocusedOut(void* data, Evas_Object*, void*);
   static void OnBeforeFormRepostWarningShow(void*, Evas_Object*, void*);
+  static void DisplayQRCode(void*, Evas_Object*, void*);
+  static void CloseQRCode(void*, Evas_Object*, void*);
+  static void CancelAuthentication(void* data, Evas_Object*, void*);
   static void OnFormRepostWarningShow(void*, Evas_Object*, void*);
   static void OnUserFormRepostDecisionTaken(bool decision, void* data);
   static void OnThemeColorChanged(Evas_Object* o,
@@ -135,6 +138,9 @@ class Window {
   Evas_Object* window_;
   Evas_Object* web_view_;
   Evas_Object* web_view_elm_host_;
+  Evas_Object* qr_window_;
+  Evas_Object* qr_img_;
+  Evas_Object* layout_;
   bool is_fullscreen_;
 };