Registration.js (4500B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const { 8 createFactory, 9 PureComponent, 10 } = require("resource://devtools/client/shared/vendor/react.mjs"); 11 12 const { 13 connect, 14 } = require("resource://devtools/client/shared/vendor/react-redux.js"); 15 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs"); 16 17 const { 18 article, 19 aside, 20 h2, 21 header, 22 li, 23 p, 24 time, 25 ul, 26 } = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); 27 28 const { 29 getUnicodeUrl, 30 } = require("resource://devtools/client/shared/unicode-url.js"); 31 32 const FluentReact = require("resource://devtools/client/shared/vendor/fluent-react.js"); 33 const Localized = createFactory(FluentReact.Localized); 34 35 const Types = require("resource://devtools/client/application/src/types/index.js"); 36 37 const { 38 unregisterWorker, 39 } = require("resource://devtools/client/application/src/actions/workers.js"); 40 41 const UIButton = createFactory( 42 require("resource://devtools/client/application/src/components/ui/UIButton.js") 43 ); 44 45 const Worker = createFactory( 46 require("resource://devtools/client/application/src/components/service-workers/Worker.js") 47 ); 48 49 /** 50 * This component is dedicated to display a service worker registration, along 51 * the list of attached workers to it. 52 * It displays information about the registration as well as an Unregister 53 * button. 54 */ 55 class Registration extends PureComponent { 56 static get propTypes() { 57 return { 58 className: PropTypes.string, 59 isDebugEnabled: PropTypes.bool.isRequired, 60 registration: PropTypes.shape(Types.registration).isRequired, 61 // this prop get automatically injected via `connect` 62 dispatch: PropTypes.func.isRequired, 63 }; 64 } 65 66 constructor(props) { 67 super(props); 68 69 this.unregister = this.unregister.bind(this); 70 } 71 72 unregister() { 73 this.props.dispatch(unregisterWorker(this.props.registration)); 74 } 75 76 isActive() { 77 const { workers } = this.props.registration; 78 return workers.some( 79 x => x.state === Ci.nsIServiceWorkerInfo.STATE_ACTIVATED 80 ); 81 } 82 83 formatScope(scope) { 84 const [, remainder] = getUnicodeUrl(scope).split("://"); 85 // remove the last slash from the url, if present 86 // or return the full scope if there's no remainder 87 return remainder ? remainder.replace(/\/$/, "") : scope; 88 } 89 90 render() { 91 const { registration, isDebugEnabled, className } = this.props; 92 93 const unregisterButton = this.isActive() 94 ? Localized( 95 { id: "serviceworker-worker-unregister" }, 96 UIButton({ 97 onClick: this.unregister, 98 className: "js-unregister-button", 99 }) 100 ) 101 : null; 102 103 const lastUpdated = registration.lastUpdateTime 104 ? Localized( 105 { 106 id: "serviceworker-worker-updated", 107 // XXX: $date should normally be a Date object, but we pass the timestamp as a 108 // workaround. See Bug 1465718. registration.lastUpdateTime is in microseconds, 109 // convert to a valid timestamp in milliseconds by dividing by 1000. 110 $date: registration.lastUpdateTime / 1000, 111 time: time({ className: "js-sw-updated" }), 112 }, 113 p({ className: "registration__updated-time" }) 114 ) 115 : null; 116 117 const scope = h2( 118 { 119 title: registration.scope, 120 className: "registration__scope js-sw-scope devtools-ellipsis-text", 121 }, 122 this.formatScope(registration.scope) 123 ); 124 125 return li( 126 { className: className ? className : "" }, 127 article( 128 { className: "registration js-sw-container" }, 129 header({ className: "registration__header" }, scope, lastUpdated), 130 aside({ className: "registration__controls" }, unregisterButton), 131 // render list of workers 132 ul( 133 { className: "registration__workers" }, 134 registration.workers.map(worker => { 135 return li( 136 { 137 key: worker.id, 138 className: "registration__workers-item", 139 }, 140 Worker({ 141 worker, 142 isDebugEnabled, 143 }) 144 ); 145 }) 146 ) 147 ) 148 ); 149 } 150 } 151 152 const mapDispatchToProps = dispatch => ({ dispatch }); 153 module.exports = connect(mapDispatchToProps)(Registration);