联合凭据管理

FedCM,简称,是一个需要完整堆栈实现的平台特性。因此,其代码分散在整个代码库中,难以追踪执行流程。本文档旨在简化这两个方面。

代码位置

与之相关的代码可以在以下所有位置找到。

此规范的 WebIDL 位于 dom/webidl/IdentityCredential.webidl

核心规范算法逻辑和 IdentityCredential 的实现位于 dom/credentialmanagement/identity/IdentityCredential.{cpp,h}IdentityCredential 的静态函数是规范算法逻辑。管理 IdentityCredential.webidl 对象的辅助函数位于 dom/credentialmanagement/identity/ 中的其他文件中。IPC 在 dom/ipc/PWindowGlobal.ipdldom/ipc/WindowGlobalParent.cpp 中的 WindowGlobal 上定义,并且是一个非常薄的层。

用于管理与 IdentityCredentials 相关联的状态的服务是 IdentityCredentialStorageService,用于管理与 IdentityCredentials 相关联的 UI 提示的服务是 IdentityCredentialPromptService。这两个定义和实现都在 toolkit/components/credentialmanagement 中。

UI 面板分散在几个地方。实际的 DOM 元素位于根节点为 #identity-credential-notification 的 HTML 子树中,位于 browser/base/content/popup-notifications.inc。但是描述它的 CSS 分散在 browser/themes/shared/customizableui/panelUI-shared.cssbrowser/themes/shared/identity-credential-notification.cssbrowser/themes/shared/notification-icons.css 中。一般来说,在这些文件中搜索 identity-credential 以找到相关的 ID 和类。

内容字符串:browser/locales/en-US/browser/identityCredentialNotification.ftl

所有这些都从 navigator.credentials 对象中输入,该对象在 dom/credentialmanagement/CredentialsContainer.{cpp,h} 中实现。

执行流程

这是与核心规范算法相关的代码的总体流程,恰好是我认为比较复杂的部分。

一些说明

  • 所有未指定类的函数都在 IdentityCredential 中。

  • IdentityCredentialPromptService 中的函数修改 Chrome DOM

  • FetchT 函数通过 mozilla::dom::FetchJSONStructure<T> 发送网络请求。

  • PromptUserWithPolicy 中进行 IdentityCredentialStorageService 调用

digraph fedcm {
  "RP (visited page) calls ``navigator.credentials.get()``" -> "CredentialsContainer::Get"
  "CredentialsContainer::Get" -> "DiscoverFromExternalSource"
  "DiscoverFromExternalSource" -> "DiscoverFromExternalSourceInMainProcess" [label="IPC via WindowGlobal's DiscoverIdentityCredentialFromExternalSource"]
  "DiscoverFromExternalSourceInMainProcess" -> "anonymous timeout callback" -> "CloseUserInterface" -> "IdentityCredentialPromptService::Close"
  "DiscoverFromExternalSourceInMainProcess" -> "CheckRootManifest A"
  "CheckRootManifest A" -> "FetchInternalManifest A" [label="via promise chain in DiscoverFromExternalSourceInMainProcess"]
  "FetchInternalManifest A" -> "DiscoverFromExternalSourceInMainProcess inline anonymous callback (Promise::All)"
  "DiscoverFromExternalSourceInMainProcess" -> "CheckRootManifest N"
  "CheckRootManifest N" -> "FetchInternalManifest N" [label="via promise chain in DiscoverFromExternalSourceInMainProcess"]
  "FetchInternalManifest N" -> "DiscoverFromExternalSourceInMainProcess inline anonymous callback (Promise::All)"
  "DiscoverFromExternalSourceInMainProcess inline anonymous callback (Promise::All)" -> "PromptUserToSelectProvider"
  "PromptUserToSelectProvider" -> "IdentityCredentialPromptService::ShowProviderPrompt"
  "IdentityCredentialPromptService::ShowProviderPrompt" -> "CreateCredential" [label="via promise chain in DiscoverFromExternalSourceInMainProcess"]
  "CreateCredential" -> "FetchAccountList" [label="via promise chain in CreateCredential"]
  "FetchAccountList" -> "PromptUserToSelectAccount" [label="via promise chain in CreateCredential"]
  "PromptUserToSelectAccount" -> "IdentityCredentialPromptService::ShowAccountListPrompt"
  "IdentityCredentialPromptService::ShowAccountListPrompt" -> "PromptUserWithPolicy" [label="via promise chain in CreateCredential"]
  "PromptUserWithPolicy" -> "FetchMetadata"
  "FetchMetadata" -> "IdentityCredentialPromptService::ShowPolicyPrompt" [label="via promise chain in PromptUserWithPolicy"]
  "IdentityCredentialPromptService::ShowPolicyPrompt" -> "FetchToken" [label="via promise chain in CreateCredential"]
  "FetchToken" -> "cancel anonymous timeout callback"
  "FetchToken" -> "CreateCredential inline anonymous callback"
  "CreateCredential inline anonymous callback" -> "DiscoverFromExternalSourceInMainProcess inline anonymous callback"
  "DiscoverFromExternalSourceInMainProcess inline anonymous callback" -> "DiscoverFromExternalSource inline anonymous callback" [label="Resolving IPC via WindowGlobal's DiscoverIdentityCredentialFromExternalSource"]
  "DiscoverFromExternalSource inline anonymous callback" -> "CredentialsContainer::Get inline anonymous callback"
  "CredentialsContainer::Get inline anonymous callback" -> "RP (visited page) gets the credential"
}