UNPKG

@react-native/debugger-frontend

Version:
2 lines (1 loc) • 19.5 kB
import*as t from"../../ui/legacy/legacy.js";import*as e from"../../core/common/common.js";import*as i from"../../core/host/host.js";import*as a from"../../core/i18n/i18n.js";import*as o from"../../core/sdk/sdk.js";import*as n from"../../ui/legacy/components/data_grid/data_grid.js";import*as r from"../../ui/visual_logging/visual_logging.js";var s={cssText:`.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{padding:0 var(--sys-size-9);min-height:auto;display:none}.webauthn-pane.enabled .authenticators-view{display:block}.new-authenticator-title{display:block;padding:var(--sys-size-7) 0 var(--sys-size-5) 0;font:var(--sys-typescale-headline5);&:has(devtools-button){padding-top:var(--sys-size-4)}}.new-authenticator-container{display:none;padding-left:var(--sys-size-9)}.authenticator-option{> select, > devtools-button{margin:0 var(--sys-size-9) var(--sys-size-3) var(--sys-size-9)}> dt-checkbox{margin:0 var(--sys-size-9) 0 var(--sys-size-8)}}.webauthn-pane.enabled .new-authenticator-container{display:block}.new-authenticator-form{border:none;flex:0 0 auto;margin:0;padding-bottom:var(--sys-size-5)}.webauthn-pane select{width:120px}.authenticator-section{display:block}.divider{border-bottom:var(--sys-size-1) solid var(--sys-color-divider);margin:10px calc(var(--sys-size-9) * -1) 0}.authenticator-fields{border:none;flex:0 0 auto;margin-bottom:10px}.authenticator-section-header{margin:var(--sys-size-4) 0 var(--sys-size-5) calc(var(--sys-size-5) * -1);display:flex;justify-content:space-between;align-items:flex-end}.authenticator-section-title{line-height:24px;display:inline-flex}.authenticator-section-title .authenticator-name-field{display:inline-block;border:none;animation:save-flash 0.2s;text-overflow:ellipsis;font:var(--sys-typescale-headline5)}.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{font:var(--sys-typescale-monospace-regular);line-height:18px}.authenticator-option-checkbox{position:relative;top:2px}.authenticator-field{margin:var(--sys-size-3) 0}.authenticator-field,\n.authenticator-option{display:flex;align-items:center}.authenticator-option-label{color:var(--sys-color-on-surface-subtle);font:var(--sys-typescale-body5-medium);padding-right:var(--sys-size-6);text-align:left;min-width:150px;line-height:18px}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:var(--sys-typescale-headline5);padding:var(--sys-size-7) 0 var(--sys-size-5) 0;border-top:var(--sys-size-1) solid var(--sys-color-divider);margin-right:calc(var(--sys-size-9) * -1)}.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=${import.meta.resolve("./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",noAuthenticator:"No authenticator set up",useWebauthnForPhishingresistant:"Use WebAuthn for phishing-resistant authentication.",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=a.i18n.registerUIStrings("panels/webauthn/WebauthnPane.ts",l),d=a.i18n.getLocalizedString.bind(void 0,c);class h extends n.DataGrid.DataGridNode{credential;constructor(t){super(t),this.credential=t}nodeSelfHeight(){return 24}createCell(e){const i=super.createCell(e);if(t.Tooltip.Tooltip.install(i,i.textContent||""),"actions"!==e)return i;const a=t.UIUtils.createTextButton(d(l.export),(()=>{this.dataGrid&&this.dataGrid.dispatchEventToListeners("ExportCredential",this.credential)}),{jslogContext:"webauthn.export-credential"});i.appendChild(a);const o=t.UIUtils.createTextButton(d(l.remove),(()=>{this.dataGrid&&this.dataGrid.dispatchEventToListeners("RemoveCredential",this.credential)}),{jslogContext:"webauthn.remove-credential"});return i.appendChild(o),i}}class u extends n.DataGrid.DataGridImpl{}class p extends(e.ObjectWrapper.eventMixin(u)){}class b extends n.DataGrid.DataGridNode{createCells(t){t.removeChildren();const e=this.createTDWithClass("center");this.dataGrid&&(e.colSpan=this.dataGrid.visibleColumnsArray.length);const i=document.createElement("span",{is:"source-code"});i.textContent="navigator.credentials.create()",i.classList.add("code");const o=a.i18n.getFormatLocalizedString(c,l.noCredentialsTryCallingSFromYour,{PH1:i});e.appendChild(o),t.appendChild(e)}}const v="PRIVATE",m=`-----BEGIN ${v} KEY-----\n`,C=`-----END ${v} KEY-----`,g={Ctap2:"ctap2",U2f:"u2f"};class x extends t.Widget.VBox{#t=null;#e=!1;dataGrids=new Map;#i;#a;#o;#n;#r;#s;#l;#c;#d;#h;transportSelect;#u;residentKeyCheckbox;#p;#b;#v;largeBlobCheckbox;addAuthenticatorButton;#m;constructor(){super(!0),this.registerRequiredCSS(s),this.element.setAttribute("jslog",`${r.panel("webauthn").track({resize:!0})}`),o.TargetManager.TargetManager.instance().observeModels(o.WebAuthnModel.WebAuthnModel,this,{scoped:!0}),this.contentElement.classList.add("webauthn-pane"),this.#a=e.Settings.Settings.instance().createSetting("webauthn-authenticators",[]),this.#C(),this.#n=this.contentElement.createChild("div","authenticators-view"),this.#g(),this.#x(!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.#y(e,i),i.authenticatorId=e,i.active&&(t=e)}this.#a.set(e),t&&this.#k(t)}async ownerViewDisposed(){this.#i&&this.#i.setChecked(!1),await this.#f(!1)}#C(){this.#r=this.contentElement.createChild("div","webauthn-toolbar-container"),this.#r.setAttribute("jslog",`${r.toolbar()}`),this.#r.role="toolbar",this.#s=this.#r.createChild("devtools-toolbar","webauthn-toolbar"),this.#s.role="presentation";const e=d(l.enableVirtualAuthenticator);this.#i=new t.Toolbar.ToolbarCheckbox(e,e,this.#w.bind(this)),this.#i.inputElement.setAttribute("jslog",`${r.toggle("virtual-authenticators").track({click:!0})}`),this.#s.appendToolbarItem(this.#i)}#S(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 p(i);return a.renderInline(),a.setStriped(!0),a.addEventListener("ExportCredential",this.#E,this),a.addEventListener("RemoveCredential",this.#L.bind(this,t)),a.rootNode().appendChild(new b),this.dataGrids.set(t,a),a}#E({data:t}){this.#I(t)}#L(t,{data:e}){this.#T(t,e.credentialId)}#U(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)}#V(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)}#B(t,{data:e}){const i=this.dataGrids.get(t);if(!i)return;const a=i.rootNode().children.find((t=>t.data?.credentialId===e.credentialId));a&&a.remove()}async#f(t){await this.#m,this.#m=new Promise((async e=>{t&&!this.#e&&(i.userMetrics.actionTaken(i.UserMetrics.Action.VirtualAuthenticatorEnvironmentEnabled),this.#e=!0),this.#o&&await this.#o.setVirtualAuthEnvEnabled(t),t?await this.#A():this.#N(),this.#x(t),this.#m=void 0,e()}))}#x(t){this.contentElement.classList.toggle("enabled",t)}#N(){this.#n.innerHTML="";for(const t of this.dataGrids.values())t.asWidget().detach();this.dataGrids.clear()}#w(t){this.#f(t.target.checked)}#K(e){if(!this.transportSelect)return;const i=this.transportSelect.value;this.transportSelect.removeChildren();for(const i of e)this.transportSelect.appendChild(t.UIUtils.createOption(i,i,i));this.transportSelect.value=i,this.transportSelect.value||(this.transportSelect.selectedIndex=0),this.#z()}#z(){if(!this.transportSelect?.options)return;const t=Boolean(this.#a.get().find((t=>"internal"===t.transport)));for(let e=0;e<this.transportSelect.options.length;++e){const i=this.transportSelect.options[e];if("internal"===i.value){i.disabled=t,e===this.transportSelect.selectedIndex&&--this.transportSelect.selectedIndex;break}}}#G(){this.#h&&this.residentKeyCheckbox&&this.#b&&this.largeBlobCheckbox&&("ctap2"===this.#h.value?(this.residentKeyCheckbox.disabled=!1,this.#b.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.#b.checked=!1,this.#b.disabled=!0,this.largeBlobCheckbox.checked=!1,this.largeBlobCheckbox.disabled=!0,this.#K(["usb","ble","nfc"])))}#g(){this.#l=new t.EmptyWidget.EmptyWidget(d(l.noAuthenticator),d(l.useWebauthnForPhishingresistant)),this.#l.element.classList.add("learn-more"),this.#l.appendLink("https://developer.chrome.com/docs/devtools/webauthn"),this.#l.show(this.contentElement),this.#c=this.contentElement.createChild("div","new-authenticator-container");const e=t.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"),n=this.#d.createChild("div","authenticator-option"),s=this.#d.createChild("div","authenticator-option"),c=this.#d.createChild("div","authenticator-option"),h=t.UIUtils.createLabel(d(l.protocol),"authenticator-option-label");i.appendChild(h),this.#h=i.createChild("select"),this.#h.setAttribute("jslog",`${r.dropDown("protocol").track({change:!0})}`),t.ARIAUtils.bindLabelToControl(h,this.#h),Object.values(g).sort().forEach((e=>{this.#h&&this.#h.appendChild(t.UIUtils.createOption(e,e,e))})),this.#h&&(this.#h.value="ctap2");const u=t.UIUtils.createLabel(d(l.transport),"authenticator-option-label");a.appendChild(u),this.transportSelect=a.createChild("select"),this.transportSelect.setAttribute("jslog",`${r.dropDown("transport").track({change:!0})}`),t.ARIAUtils.bindLabelToControl(u,this.transportSelect),this.#u=t.UIUtils.CheckboxLabel.create(d(l.supportsResidentKeys),!1,void 0,"resident-key"),this.#u.textElement.classList.add("authenticator-option-label"),o.appendChild(this.#u.textElement),this.residentKeyCheckbox=this.#u.checkboxElement,this.residentKeyCheckbox.checked=!1,this.residentKeyCheckbox.classList.add("authenticator-option-checkbox"),o.appendChild(this.#u),this.#p=t.UIUtils.CheckboxLabel.create(d(l.supportsUserVerification),!1,void 0,"user-verification"),this.#p.textElement.classList.add("authenticator-option-label"),n.appendChild(this.#p.textElement),this.#b=this.#p.checkboxElement,this.#b.checked=!1,this.#b.classList.add("authenticator-option-checkbox"),n.appendChild(this.#p),this.#v=t.UIUtils.CheckboxLabel.create(d(l.supportsLargeBlob),!1,void 0,"large-blob"),this.#v.textElement.classList.add("authenticator-option-label"),s.appendChild(this.#v.textElement),this.largeBlobCheckbox=this.#v.checkboxElement,this.largeBlobCheckbox.checked=!1,this.largeBlobCheckbox.classList.add("authenticator-option-checkbox"),this.largeBlobCheckbox.name="large-blob-checkbox",s.appendChild(this.#v),this.addAuthenticatorButton=t.UIUtils.createTextButton(d(l.add),this.#j.bind(this),{jslogContext:"webauthn.add-authenticator"}),c.createChild("div","authenticator-option-label"),c.appendChild(this.addAuthenticatorButton);const p=t.UIUtils.createLabel(d(l.addAuthenticator),"");t.ARIAUtils.bindLabelToControl(p,this.addAuthenticatorButton),this.#G(),this.#h&&this.#h.addEventListener("change",this.#G.bind(this)),this.residentKeyCheckbox&&this.residentKeyCheckbox.addEventListener("change",this.#G.bind(this))}async#j(){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.#y(e,t),o=window.matchMedia("(prefers-reduced-motion: reduce)").matches;a.scrollIntoView({block:"start",behavior:o?"auto":"smooth"}),this.#z()}}async#y(e,i){const a=document.createElement("div");a.classList.add("authenticator-section"),a.setAttribute("data-authenticator-id",e),a.setAttribute("jslog",`${r.section("authenticator")}`),this.#n.appendChild(a);const o=a.createChild("div","authenticator-section-header"),n=o.createChild("div","authenticator-section-title");t.ARIAUtils.markAsHeading(n,2),await this.#F();const s=o.createChild("div","active-button-container"),{label:c,radio:h}=t.UIUtils.createRadioButton("active-authenticator",d(l.active),"webauthn.active-authenticator");h.addEventListener("change",this.#k.bind(this,e)),h.checked=!0,s.appendChild(c),this.#t=e;const u=o.createChild("button","text-button");u.textContent=d(l.remove),u.addEventListener("click",this.removeAuthenticator.bind(this,e)),u.setAttribute("jslog",`${r.action("webauthn.remove-authenticator").track({click:!0})}`);const p=n.createChild("devtools-toolbar","edit-name-toolbar"),b=new t.Toolbar.ToolbarButton(d(l.editName),"edit",void 0,"edit-name"),v=new t.Toolbar.ToolbarButton(d(l.saveName),"checkmark",void 0,"save-name");v.setVisible(!1);const m=n.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=e.slice(-5);m.value=d(l.authenticatorS,{PH1:C}),this.#P(c,m.value),b.addEventListener("Click",(()=>this.#D(n,m,b,v))),v.addEventListener("Click",(()=>this.#M(n,m,b,v,c))),m.addEventListener("focusout",(()=>this.#M(n,m,b,v,c))),m.addEventListener("keydown",(t=>{"Enter"===t.key&&this.#M(n,m,b,v,c)})),p.appendToolbarItem(b),p.appendToolbarItem(v),this.#O(a,e,i);const g=document.createElement("div");g.classList.add("credentials-title"),g.textContent=d(l.credentials),a.appendChild(g);return this.#S(e).asWidget().show(a),this.#o&&(this.#o.addEventListener("CredentialAdded",this.#U.bind(this,e)),this.#o.addEventListener("CredentialAsserted",this.#V.bind(this,e)),this.#o.addEventListener("CredentialUpdated",this.#V.bind(this,e)),this.#o.addEventListener("CredentialDeleted",this.#B.bind(this,e))),a.createChild("div","divider"),a}#I(t){let e=m;for(let i=0;i<t.privateKey.length;i+=64)e+=t.privateKey.substring(i,i+64)+"\n";e+=C;const i=document.createElement("a");i.download=d(l.privateKeypem),i.href="data:application/x-pem-file,"+encodeURIComponent(e),i.click()}async#T(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 b),this.#o&&await this.#o.removeCredential(t,e))}#O(e,i,a){const o=e.createChild("div","authenticator-fields"),n=o.createChild("div","authenticator-field"),r=o.createChild("div","authenticator-field"),s=o.createChild("div","authenticator-field"),c=o.createChild("div","authenticator-field"),h=o.createChild("div","authenticator-field"),u=o.createChild("div","authenticator-field");n.appendChild(t.UIUtils.createLabel(d(l.uuid),"authenticator-option-label")),r.appendChild(t.UIUtils.createLabel(d(l.protocol),"authenticator-option-label")),s.appendChild(t.UIUtils.createLabel(d(l.transport),"authenticator-option-label")),c.appendChild(t.UIUtils.createLabel(d(l.supportsResidentKeys),"authenticator-option-label")),h.appendChild(t.UIUtils.createLabel(d(l.supportsLargeBlob),"authenticator-option-label")),u.appendChild(t.UIUtils.createLabel(d(l.supportsUserVerification),"authenticator-option-label")),n.createChild("div","authenticator-field-value").textContent=i,r.createChild("div","authenticator-field-value").textContent=a.protocol,s.createChild("div","authenticator-field-value").textContent=a.transport,c.createChild("div","authenticator-field-value").textContent=a.hasResidentKey?d(l.yes):d(l.no),h.createChild("div","authenticator-field-value").textContent=a.hasLargeBlob?d(l.yes):d(l.no),u.createChild("div","authenticator-field-value").textContent=a.hasUserVerification?d(l.yes):d(l.no)}#D(t,e,i,a){e.disabled=!1,t.classList.add("editing-name"),e.focus(),a.setVisible(!0),i.setVisible(!1)}#M(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.#P(o,n))}#P(e,i){t.Tooltip.Tooltip.install(e,d(l.setSAsTheActiveAuthenticator,{PH1:i}))}removeAuthenticator(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.#k(t[0]):this.#t=null}this.#z()}#R(){if(!(this.#h&&this.transportSelect&&this.residentKeyCheckbox&&this.#b&&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.transportSelect.options[this.transportSelect.selectedIndex].value,hasResidentKey:this.residentKeyCheckbox.checked,hasUserVerification:this.#b.checked,hasLargeBlob:this.largeBlobCheckbox.checked,automaticPresenceSimulation:!0,isUserVerified:!0}}async#k(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.#W()}#W(){const t=this.#n.getElementsByClassName("authenticator-section");Array.from(t).forEach((t=>{const e=t.querySelector('input[type="radio"]');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.#W()}}var A=Object.freeze({__proto__:null,WebauthnPaneImpl:x});export{A as WebauthnPane};