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 file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5import React from "react"; 6import ReactDOM from "react-dom"; 7import { MultiStageAboutWelcome } from "./components/MultiStageAboutWelcome"; 8import { ReturnToAMO } from "./components/ReturnToAMO"; 9 10class AboutWelcome extends React.PureComponent { 11 constructor(props) { 12 super(props); 13 this.state = { metricsFlowUri: null }; 14 this.fetchFxAFlowUri = this.fetchFxAFlowUri.bind(this); 15 } 16 17 async fetchFxAFlowUri() { 18 this.setState({ metricsFlowUri: await window.AWGetFxAMetricsFlowURI() }); 19 } 20 21 componentDidMount() { 22 if (!this.props.skipFxA) { 23 this.fetchFxAFlowUri(); 24 } 25 26 // Rely on shared proton in-content styling for consistency. 27 if (this.props.design === "proton") { 28 const sheet = document.head.appendChild(document.createElement("link")); 29 sheet.rel = "stylesheet"; 30 sheet.href = "chrome://global/skin/in-content/common.css"; 31 } 32 33 // Record impression with performance data after allowing the page to load 34 const recordImpression = domState => { 35 const { domComplete, domInteractive } = performance 36 .getEntriesByType("navigation") 37 .pop(); 38 window.AWSendEventTelemetry({ 39 event: "IMPRESSION", 40 event_context: { 41 domComplete, 42 domInteractive, 43 mountStart: performance.getEntriesByName("mount").pop().startTime, 44 domState, 45 source: this.props.UTMTerm, 46 page: "about:welcome", 47 }, 48 message_id: this.props.messageId, 49 }); 50 }; 51 if (document.readyState === "complete") { 52 // Page might have already triggered a load event because it waited for async data, 53 // e.g., attribution, so the dom load timing could be of a empty content 54 // with domState in telemetry captured as 'complete' 55 recordImpression(document.readyState); 56 } else { 57 window.addEventListener("load", () => recordImpression("load"), { 58 once: true, 59 }); 60 } 61 62 // Captures user has seen about:welcome by setting 63 // firstrun.didSeeAboutWelcome pref to true and capturing welcome UI unique messageId 64 window.AWSendToParent("SET_WELCOME_MESSAGE_SEEN", this.props.messageId); 65 } 66 67 render() { 68 const { props } = this; 69 if (props.template === "return_to_amo") { 70 return ( 71 <ReturnToAMO 72 message_id={props.messageId} 73 name={props.name} 74 url={props.url} 75 iconURL={props.iconURL} 76 /> 77 ); 78 } 79 80 return ( 81 <MultiStageAboutWelcome 82 screens={props.screens} 83 metricsFlowUri={this.state.metricsFlowUri} 84 message_id={props.messageId} 85 utm_term={props.UTMTerm} 86 design={props.design} 87 transitions={props.transitions} 88 background_url={props.background_url} 89 /> 90 ); 91 } 92} 93 94// Computes messageId and UTMTerm info used in telemetry 95function ComputeTelemetryInfo(welcomeContent, experimentId, branchId) { 96 let messageId = 97 welcomeContent.template === "return_to_amo" 98 ? "RTAMO_DEFAULT_WELCOME" 99 : "DEFAULT_ABOUTWELCOME"; 100 let UTMTerm = "default"; 101 102 if (welcomeContent.id) { 103 messageId = welcomeContent.id.toUpperCase(); 104 } 105 106 if (experimentId && branchId) { 107 UTMTerm = `${experimentId}-${branchId}`.toLowerCase(); 108 } 109 return { 110 messageId, 111 UTMTerm, 112 }; 113} 114 115async function retrieveRenderContent() { 116 // Feature config includes RTAMO attribution data if exists 117 // else below data in order specified 118 // user prefs 119 // experiment data 120 // defaults 121 let featureConfig = await window.AWGetFeatureConfig(); 122 123 let { messageId, UTMTerm } = ComputeTelemetryInfo( 124 featureConfig, 125 featureConfig.slug, 126 featureConfig.branch && featureConfig.branch.slug 127 ); 128 return { featureConfig, messageId, UTMTerm }; 129} 130 131async function mount() { 132 let { 133 featureConfig: aboutWelcomeProps, 134 messageId, 135 UTMTerm, 136 } = await retrieveRenderContent(); 137 ReactDOM.render( 138 <AboutWelcome 139 messageId={messageId} 140 UTMTerm={UTMTerm} 141 {...aboutWelcomeProps} 142 />, 143 document.getElementById("root") 144 ); 145} 146 147performance.mark("mount"); 148mount(); 149