JSDoc style comments are used within the JS files of the component. This document will focus on higher-level and shared concepts.
Set the pref
dom.payments.loglevel to “Debug” to increase the verbosity of console messages.
Unprivileged UI Development¶
During development of the unprivileged custom elements, you can load the dialog from a local server without even requiring a build. Simply run ./mach python browser/components/payments/server.py then load http://localhost:8000/paymentRequest.xhtml?debug=1 in the browser. Use the debugging console to load sample data.
To open the debugging console in the dialog, use the keyboard shortcut Ctrl-Alt-d (Ctrl-Option-d on macOS). While loading paymentRequest.xhtml directly in the browser, add ?debug=1 to have the debugging console open by default.
Debugging the unprivileged frame with the developer tools¶
To open a debugger in the context of the remote payment frame, click the “Debug frame” button in the debugging console.
Use the tabs variable in the Browser Content Toolbox’s console to access the frame contents. There can be multiple frames loaded in the same process so you will need to find the correct tab in the array by checking the file name is paymentRequest.xhtml (e.g. tabs.content.location).
Communication with the DOM¶
Communication from the DOM to the UI happens via the paymentUIService.js (implementing
The UI talks to the DOM code via the
Privileged wrapper XUL document (paymentDialogWrapper.xul) containing a remote
<xul:browser="true" remote="true"> containing unprivileged XHTML (paymentRequest.xhtml).
Keeping the dialog contents unprivileged is useful since the dialog will render payment line items and shipping options that are provided by web developers and should therefore be considered untrusted.
In order to communicate across the process boundary a privileged frame script (paymentDialogFrameScript.js) is loaded into the iframe to relay messages.
This is because the unprivileged document cannot access message managers.
Instead, all communication across the privileged/unprivileged boundary is done via custom DOM events:
paymentContentToChromeevent is dispatched when the dialog contents want to communicate with the privileged dialog wrapper.
paymentChromeToContentevent is dispatched on the
detailproperty populated when the privileged dialog wrapper communicates with the unprivileged dialog.
These events are converted to/from message manager messages of the same name to communicate to the other process. The purpose of paymentDialogFrameScript.js is to simply convert unprivileged DOM events to/from messages from the other process.
The Payment Request UI uses Custom Elements for the UI components.
Some guidelines: * If you’re overriding a lifecycle callback, don’t forget to call that method on
superfrom the implementation to ensure that mixins and ancestor classes work properly.
- From within a custom element, don’t use
document.querySelector*because they can return elements that are outside of the component, thus breaking the modularization. It can also cause problems if the elements you’re looking for aren’t attached to the document yet. Use
this(the custom element) or one of its descendants instead.