UNPKG

@react-native/debugger-frontend

Version:
7 lines (6 loc) • 17.9 kB
import*as t from"../../core/common/common.js";import*as e from"../../core/host/host.js";import*as i from"../../core/i18n/i18n.js";import*as a from"../../core/sdk/sdk.js";import*as o from"../../ui/legacy/components/data_grid/data_grid.js";import*as n from"../../ui/legacy/legacy.js";import*as r from"../../ui/visual_logging/visual_logging.js";const s=new CSSStyleSheet;s.replaceSync('.webauthn-pane{overflow:auto;min-width:500px}.webauthn-toolbar-container{display:flex;background-color:var(--sys-color-cdt-base-container);border-bottom:1px solid var(--sys-color-divider);flex:0 0 auto}.webauthn-toolbar{display:inline-block}.authenticators-view{margin:0 10px;min-height:auto;display:none}.webauthn-pane.enabled .authenticators-view{display:block}.new-authenticator-title{line-height:24px;font-weight:bold;display:block}.new-authenticator-container{display:none;margin:10px}.webauthn-pane.enabled .new-authenticator-container{display:block}.new-authenticator-form{border:none;padding:10px 0;flex:0 0 auto;margin:0}.webauthn-pane .chrome-select{width:120px}.authenticator-section{display:block;padding:16px 0;border-bottom:1px solid var(--sys-color-divider)}.authenticator-fields{border:none;padding:10px 0;flex:0 0 auto;margin:0}.authenticator-field{display:flex;margin:auto}.authenticator-section-header{display:flex;justify-content:space-between;align-items:flex-end}.authenticator-section-title{line-height:24px;display:inline-block}.authenticator-section-title .authenticator-name-field{display:inline-block;font-weight:bold;border:none;animation:save-flash 0.2s;text-overflow:ellipsis}.authenticator-section-title.editing-name .authenticator-name-field{border-bottom:1px solid var(--sys-color-neutral-outline);font-weight:normal;animation:none}.authenticator-field-value{padding:5px 0;display:inline-block;font-family:monospace}.authenticator-option-checkbox{position:relative;top:2px}.authenticator-option{display:flex;padding-bottom:10px;align-items:center;margin:auto;&:has(span[is="dt-checkbox"]){padding-bottom:4px}}.authenticator-option-label{text-align:right;width:200px;display:inline-block;padding:0 10px 0 0}td .text-button{min-width:20px;margin:auto}.active-button-container{display:inline-block;min-width:28px}.edit-name-toolbar{display:inline-block;vertical-align:middle}@keyframes save-flash{from{opacity:0%}to{opacity:100%}}.data-grid-data-grid-node.centered{text-align:center}.data-grid td{vertical-align:middle}.credentials-title{display:block;font-weight:bold;margin:8px 0}.code{font-family:monospace}.learn-more{display:flex;justify-content:center;align-items:center;height:100%;text-align:center;overflow:hidden}.webauthn-pane.enabled .learn-more{display:none}\n/*# sourceURL=webauthnPane.css */\n');const l={export:"Export",remove:"Remove",noCredentialsTryCallingSFromYour:"No credentials. Try calling {PH1} from your website.",enableVirtualAuthenticator:"Enable virtual authenticator environment",id:"ID",isResident:"Is Resident",rpId:"RP ID",userHandle:"User Handle",signCount:"Signature Count",actions:"Actions",credentials:"Credentials",useWebauthnForPhishingresistant:"Use WebAuthn for phishing-resistant authentication",learnMore:"Learn more",newAuthenticator:"New authenticator",protocol:"Protocol",transport:"Transport",supportsResidentKeys:"Supports resident keys",supportsLargeBlob:"Supports large blob",add:"Add",addAuthenticator:"Add authenticator",active:"Active",editName:"Edit name",enterNewName:"Enter new name",saveName:"Save name",authenticatorS:"Authenticator {PH1}",privateKeypem:"Private key.pem",uuid:"UUID",supportsUserVerification:"Supports user verification",yes:"Yes",no:"No",setSAsTheActiveAuthenticator:"Set {PH1} as the active authenticator"},c=i.i18n.registerUIStrings("panels/webauthn/WebauthnPane.ts",l),d=i.i18n.getLocalizedString.bind(void 0,c);class h extends o.DataGrid.DataGridNode{credential;constructor(t){super(t),this.credential=t}nodeSelfHeight(){return 24}createCell(t){const e=super.createCell(t);if(n.Tooltip.Tooltip.install(e,e.textContent||""),"actions"!==t)return e;const i=n.UIUtils.createTextButton(d(l.export),(()=>{this.dataGrid&&this.dataGrid.dispatchEventToListeners("ExportCredential",this.credential)}),{jslogContext:"webauthn.export-credential"});e.appendChild(i);const a=n.UIUtils.createTextButton(d(l.remove),(()=>{this.dataGrid&&this.dataGrid.dispatchEventToListeners("RemoveCredential",this.credential)}),{jslogContext:"webauthn.remove-credential"});return e.appendChild(a),e}}class u extends o.DataGrid.DataGridImpl{}class b extends(t.ObjectWrapper.eventMixin(u)){}class p extends o.DataGrid.DataGridNode{createCells(t){t.removeChildren();const e=this.createTDWithClass("center");this.dataGrid&&(e.colSpan=this.dataGrid.visibleColumnsArray.length);const a=document.createElement("span",{is:"source-code"});a.textContent="navigator.credentials.create()",a.classList.add("code");const o=i.i18n.getFormatLocalizedString(c,l.noCredentialsTryCallingSFromYour,{PH1:a});e.appendChild(o),t.appendChild(e)}}const m="PRIVATE",C=`-----BEGIN ${m} KEY-----\n`,v=`-----END ${m} KEY-----`,g={Ctap2:"ctap2",U2f:"u2f"};class x extends n.Widget.VBox{#t=null;#e=!1;dataGrids=new Map;#i;#a;#o;#n;#r;#s;#l;#c;#d;#h;#u;#b;residentKeyCheckbox;#p;#m;#C;largeBlobCheckbox;addAuthenticatorButton;#v;constructor(){super(!0),this.element.setAttribute("jslog",`${r.panel("webauthn").track({resize:!0})}`),a.TargetManager.TargetManager.instance().observeModels(a.WebAuthnModel.WebAuthnModel,this,{scoped:!0}),this.contentElement.classList.add("webauthn-pane"),this.#a=t.Settings.Settings.instance().createSetting("webauthn-authenticators",[]),this.#g(),this.#n=this.contentElement.createChild("div","authenticators-view"),this.#x(),this.#k(!1)}modelAdded(t){t.target()===t.target().outermostTarget()&&(this.#o=t)}modelRemoved(t){t.target()===t.target().outermostTarget()&&(this.#o=void 0)}async#A(){let t=null;const e=this.#a.get();for(const i of e){if(!this.#o)continue;const e=await this.#o.addAuthenticator(i);this.#w(e,i),i.authenticatorId=e,i.active&&(t=e)}this.#a.set(e),t&&this.#f(t)}async ownerViewDisposed(){this.#i&&this.#i.setChecked(!1),await this.#y(!1)}#g(){this.#r=this.contentElement.createChild("div","webauthn-toolbar-container"),this.#r.setAttribute("jslog",`${r.toolbar()}`),this.#s=new n.Toolbar.Toolbar("webauthn-toolbar",this.#r);const t=d(l.enableVirtualAuthenticator);this.#i=new n.Toolbar.ToolbarCheckbox(t,t,this.#S.bind(this)),this.#i.inputElement.setAttribute("jslog",`${r.toggle("virtual-authenticators").track({click:!0})}`),this.#s.appendToolbarItem(this.#i)}#E(t){const e=[{id:"credentialId",title:d(l.id),longText:!0,weight:24},{id:"isResidentCredential",title:d(l.isResident),dataType:"Boolean",weight:10},{id:"rpId",title:d(l.rpId)},{id:"userHandle",title:d(l.userHandle)},{id:"signCount",title:d(l.signCount)},{id:"actions",title:d(l.actions)}],i={displayName:d(l.credentials),columns:e,editCallback:void 0,deleteCallback:void 0,refreshCallback:void 0},a=new b(i);return a.renderInline(),a.setStriped(!0),a.addEventListener("ExportCredential",this.#L,this),a.addEventListener("RemoveCredential",this.#I.bind(this,t)),a.rootNode().appendChild(new p),this.dataGrids.set(t,a),a}#L({data:t}){this.#T(t)}#I(t,{data:e}){this.#U(t,e.credentialId)}#V(t,{data:e}){const i=this.dataGrids.get(t);if(!i)return;const a=i.rootNode().children.find((t=>!Object.keys(t.data).length));a&&i.rootNode().removeChild(a);const o=new h(e.credential);i.rootNode().appendChild(o)}#B(t,{data:e}){const i=this.dataGrids.get(t);if(!i)return;const a=i.rootNode().children.find((t=>t.data?.credentialId===e.credential.credentialId));a&&(a.data=e.credential)}async#y(t){await this.#v,this.#v=new Promise((async i=>{t&&!this.#e&&(e.userMetrics.actionTaken(e.UserMetrics.Action.VirtualAuthenticatorEnvironmentEnabled),this.#e=!0),this.#o&&await this.#o.setVirtualAuthEnvEnabled(t),t?await this.#A():this.#N(),this.#k(t),this.#v=void 0,i()}))}#k(t){this.contentElement.classList.toggle("enabled",t)}#N(){this.#n.innerHTML="";for(const t of this.dataGrids.values())t.asWidget().detach();this.dataGrids.clear()}#S(t){this.#y(t.target.checked)}#K(t){if(!this.#u)return;const e=this.#u.value;this.#u.removeChildren();for(const e of t)this.#u.appendChild(n.UIUtils.createOption(e,e,e));this.#u.value=e,this.#u.value||(this.#u.selectedIndex=0)}#j(){this.#h&&this.residentKeyCheckbox&&this.#m&&this.largeBlobCheckbox&&("ctap2"===this.#h.value?(this.residentKeyCheckbox.disabled=!1,this.#m.disabled=!1,this.largeBlobCheckbox.disabled=!this.residentKeyCheckbox.checked,this.largeBlobCheckbox.disabled&&(this.largeBlobCheckbox.checked=!1),this.#K(["usb","ble","nfc","internal"])):(this.residentKeyCheckbox.checked=!1,this.residentKeyCheckbox.disabled=!0,this.#m.checked=!1,this.#m.disabled=!0,this.largeBlobCheckbox.checked=!1,this.largeBlobCheckbox.disabled=!0,this.#K(["usb","ble","nfc"])))}#x(){const t=n.XLink.XLink.create("https://developers.google.com/web/updates/2018/05/webauthn",d(l.learnMore),void 0,void 0,"learn-more");this.#l=this.contentElement.createChild("div","learn-more"),this.#l.appendChild(n.Fragment.html` <div> ${d(l.useWebauthnForPhishingresistant)}<br /><br /> ${t} </div> `),this.#c=this.contentElement.createChild("div","new-authenticator-container");const e=n.UIUtils.createLabel(d(l.newAuthenticator),"new-authenticator-title");this.#c.appendChild(e),this.#d=this.#c.createChild("div","new-authenticator-form"),this.#d.setAttribute("jslog",`${r.section("new-authenticator")}`);const i=this.#d.createChild("div","authenticator-option"),a=this.#d.createChild("div","authenticator-option"),o=this.#d.createChild("div","authenticator-option"),s=this.#d.createChild("div","authenticator-option"),c=this.#d.createChild("div","authenticator-option"),h=this.#d.createChild("div","authenticator-option"),u=n.UIUtils.createLabel(d(l.protocol),"authenticator-option-label");i.appendChild(u),this.#h=i.createChild("select","chrome-select"),this.#h.setAttribute("jslog",`${r.dropDown("protocol").track({change:!0})}`),n.ARIAUtils.bindLabelToControl(u,this.#h),Object.values(g).sort().forEach((t=>{this.#h&&this.#h.appendChild(n.UIUtils.createOption(t,t,t))})),this.#h&&(this.#h.value="ctap2");const b=n.UIUtils.createLabel(d(l.transport),"authenticator-option-label");a.appendChild(b),this.#u=a.createChild("select","chrome-select"),this.#u.setAttribute("jslog",`${r.dropDown("transport").track({change:!0})}`),n.ARIAUtils.bindLabelToControl(b,this.#u),this.#b=n.UIUtils.CheckboxLabel.create(d(l.supportsResidentKeys),!1,void 0,"resident-key"),this.#b.textElement.classList.add("authenticator-option-label"),o.appendChild(this.#b.textElement),this.residentKeyCheckbox=this.#b.checkboxElement,this.residentKeyCheckbox.checked=!1,this.residentKeyCheckbox.classList.add("authenticator-option-checkbox"),o.appendChild(this.#b),this.#p=n.UIUtils.CheckboxLabel.create(d(l.supportsUserVerification),!1,void 0,"user-verification"),this.#p.textElement.classList.add("authenticator-option-label"),s.appendChild(this.#p.textElement),this.#m=this.#p.checkboxElement,this.#m.checked=!1,this.#m.classList.add("authenticator-option-checkbox"),s.appendChild(this.#p),this.#C=n.UIUtils.CheckboxLabel.create(d(l.supportsLargeBlob),!1,void 0,"large-blob"),this.#C.textElement.classList.add("authenticator-option-label"),c.appendChild(this.#C.textElement),this.largeBlobCheckbox=this.#C.checkboxElement,this.largeBlobCheckbox.checked=!1,this.largeBlobCheckbox.classList.add("authenticator-option-checkbox"),this.largeBlobCheckbox.name="large-blob-checkbox",c.appendChild(this.#C),this.addAuthenticatorButton=n.UIUtils.createTextButton(d(l.add),this.#G.bind(this),{jslogContext:"webauthn.add-authenticator"}),h.createChild("div","authenticator-option-label"),h.appendChild(this.addAuthenticatorButton);const p=n.UIUtils.createLabel(d(l.addAuthenticator),"");n.ARIAUtils.bindLabelToControl(p,this.addAuthenticatorButton),this.#j(),this.#h&&this.#h.addEventListener("change",this.#j.bind(this)),this.residentKeyCheckbox&&this.residentKeyCheckbox.addEventListener("change",this.#j.bind(this))}async#G(){const t=this.#R();if(this.#o){const e=await this.#o.addAuthenticator(t),i=this.#a.get();i.push({authenticatorId:e,active:!0,...t}),this.#a.set(i.map((t=>({...t,active:t.authenticatorId===e}))));const a=await this.#w(e,t),o=window.matchMedia("(prefers-reduced-motion: reduce)").matches;a.scrollIntoView({block:"start",behavior:o?"auto":"smooth"})}}async#w(t,e){const i=document.createElement("div");i.classList.add("authenticator-section"),i.setAttribute("data-authenticator-id",t),i.setAttribute("jslog",`${r.section("authenticator")}`),this.#n.appendChild(i);const a=i.createChild("div","authenticator-section-header"),o=a.createChild("div","authenticator-section-title");n.ARIAUtils.markAsHeading(o,2),await this.#F();const s=a.createChild("div","active-button-container"),c=n.UIUtils.createRadioLabel(`active-authenticator-${t}`,d(l.active));c.radioElement.addEventListener("change",this.#f.bind(this,t)),s.appendChild(c),c.radioElement.checked=!0,this.#t=t;const h=a.createChild("button","text-button");h.textContent=d(l.remove),h.addEventListener("click",this.#P.bind(this,t)),h.setAttribute("jslog",`${r.action("webauthn.remove-authenticator").track({click:!0})}`);const u=new n.Toolbar.Toolbar("edit-name-toolbar",o),b=new n.Toolbar.ToolbarButton(d(l.editName),"edit",void 0,"edit-name"),p=new n.Toolbar.ToolbarButton(d(l.saveName),"checkmark",void 0,"save-name");p.setVisible(!1);const m=o.createChild("input","authenticator-name-field");m.placeholder=d(l.enterNewName),m.disabled=!0,m.setAttribute("jslog",`${r.textField("name").track({keydown:"Enter",change:!0})}`);const C=t.slice(-5);m.value=d(l.authenticatorS,{PH1:C}),this.#D(c,m.value),b.addEventListener("Click",(()=>this.#M(o,m,b,p))),p.addEventListener("Click",(()=>this.#O(o,m,b,p,c))),m.addEventListener("focusout",(()=>this.#O(o,m,b,p,c))),m.addEventListener("keydown",(t=>{"Enter"===t.key&&this.#O(o,m,b,p,c)})),u.appendToolbarItem(b),u.appendToolbarItem(p),this.#$(i,t,e);const v=document.createElement("div");v.classList.add("credentials-title"),v.textContent=d(l.credentials),i.appendChild(v);return this.#E(t).asWidget().show(i),this.#o&&(this.#o.addEventListener("CredentialAdded",this.#V.bind(this,t)),this.#o.addEventListener("CredentialAsserted",this.#B.bind(this,t))),i}#T(t){let e=C;for(let i=0;i<t.privateKey.length;i+=64)e+=t.privateKey.substring(i,i+64)+"\n";e+=v;const i=document.createElement("a");i.download=d(l.privateKeypem),i.href="data:application/x-pem-file,"+encodeURIComponent(e),i.click()}async#U(t,e){const i=this.dataGrids.get(t);i&&(i.rootNode().children.find((t=>t.data.credentialId===e)).remove(),i.rootNode().children.length||i.rootNode().appendChild(new p),this.#o&&await this.#o.removeCredential(t,e))}#$(t,e,i){const a=t.createChild("div","authenticator-fields"),o=a.createChild("div","authenticator-field"),r=a.createChild("div","authenticator-field"),s=a.createChild("div","authenticator-field"),c=a.createChild("div","authenticator-field"),h=a.createChild("div","authenticator-field"),u=a.createChild("div","authenticator-field");o.appendChild(n.UIUtils.createLabel(d(l.uuid),"authenticator-option-label")),r.appendChild(n.UIUtils.createLabel(d(l.protocol),"authenticator-option-label")),s.appendChild(n.UIUtils.createLabel(d(l.transport),"authenticator-option-label")),c.appendChild(n.UIUtils.createLabel(d(l.supportsResidentKeys),"authenticator-option-label")),h.appendChild(n.UIUtils.createLabel(d(l.supportsLargeBlob),"authenticator-option-label")),u.appendChild(n.UIUtils.createLabel(d(l.supportsUserVerification),"authenticator-option-label")),o.createChild("div","authenticator-field-value").textContent=e,r.createChild("div","authenticator-field-value").textContent=i.protocol,s.createChild("div","authenticator-field-value").textContent=i.transport,c.createChild("div","authenticator-field-value").textContent=i.hasResidentKey?d(l.yes):d(l.no),h.createChild("div","authenticator-field-value").textContent=i.hasLargeBlob?d(l.yes):d(l.no),u.createChild("div","authenticator-field-value").textContent=i.hasUserVerification?d(l.yes):d(l.no)}#M(t,e,i,a){e.disabled=!1,t.classList.add("editing-name"),e.focus(),a.setVisible(!0),i.setVisible(!1)}#O(t,e,i,a,o){const n=e.value;n&&(e.disabled=!0,t.classList.remove("editing-name"),i.setVisible(!0),a.setVisible(!1),this.#D(o,n))}#D(t,e){n.Tooltip.Tooltip.install(t.radioElement,d(l.setSAsTheActiveAuthenticator,{PH1:e}))}#P(t){if(this.#n){const e=this.#n.querySelector(`[data-authenticator-id=${CSS.escape(t)}]`);e&&e.remove()}const e=this.dataGrids.get(t);e&&(e.asWidget().detach(),this.dataGrids.delete(t)),this.#o&&this.#o.removeAuthenticator(t);const i=this.#a.get().filter((e=>e.authenticatorId!==t));if(this.#a.set(i),this.#t===t){const t=Array.from(this.dataGrids.keys());t.length?this.#f(t[0]):this.#t=null}}#R(){if(!(this.#h&&this.#u&&this.residentKeyCheckbox&&this.#m&&this.largeBlobCheckbox))throw new Error("Unable to create options from current inputs");return{protocol:this.#h.options[this.#h.selectedIndex].value,ctap2Version:"ctap2_1",transport:this.#u.options[this.#u.selectedIndex].value,hasResidentKey:this.residentKeyCheckbox.checked,hasUserVerification:this.#m.checked,hasLargeBlob:this.largeBlobCheckbox.checked,automaticPresenceSimulation:!0,isUserVerified:!0}}async#f(t){await this.#F(),this.#o&&await this.#o.setAutomaticPresenceSimulation(t,!0),this.#t=t;const e=this.#a.get().map((e=>({...e,active:e.authenticatorId===t})));this.#a.set(e),this.#H()}#H(){const t=this.#n.getElementsByClassName("authenticator-section");Array.from(t).forEach((t=>{const e=t.querySelector("input.dt-radio-button");e&&(e.checked=t.dataset.authenticatorId===this.#t)}))}async#F(){this.#t&&this.#o&&await this.#o.setAutomaticPresenceSimulation(this.#t,!1),this.#t=null,this.#H()}wasShown(){super.wasShown(),this.registerCSSFiles([s])}}var k=Object.freeze({__proto__:null,WebauthnPaneImpl:x});export{k as WebauthnPane};