diff options
Diffstat (limited to '')
-rw-r--r-- | browser/components/newtab/content-src/aboutwelcome/aboutwelcome.jsx | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/browser/components/newtab/content-src/aboutwelcome/aboutwelcome.jsx b/browser/components/newtab/content-src/aboutwelcome/aboutwelcome.jsx new file mode 100644 index 0000000000..d9503584b9 --- /dev/null +++ b/browser/components/newtab/content-src/aboutwelcome/aboutwelcome.jsx @@ -0,0 +1,188 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import React from "react"; +import ReactDOM from "react-dom"; +import { MultiStageAboutWelcome } from "./components/MultiStageAboutWelcome"; +import { SimpleAboutWelcome } from "./components/SimpleAboutWelcome"; +import { ReturnToAMO } from "./components/ReturnToAMO"; + +import { + AboutWelcomeUtils, + DEFAULT_WELCOME_CONTENT, +} from "../lib/aboutwelcome-utils"; + +class AboutWelcome extends React.PureComponent { + constructor(props) { + super(props); + this.state = { metricsFlowUri: null }; + this.fetchFxAFlowUri = this.fetchFxAFlowUri.bind(this); + this.handleStartBtnClick = this.handleStartBtnClick.bind(this); + } + + async fetchFxAFlowUri() { + this.setState({ metricsFlowUri: await window.AWGetFxAMetricsFlowURI() }); + } + + componentDidMount() { + this.fetchFxAFlowUri(); + + // Record impression with performance data after allowing the page to load + const recordImpression = domState => { + const { domComplete, domInteractive } = performance + .getEntriesByType("navigation") + .pop(); + window.AWSendEventTelemetry({ + event: "IMPRESSION", + event_context: { + domComplete, + domInteractive, + mountStart: performance.getEntriesByName("mount").pop().startTime, + domState, + source: this.props.UTMTerm, + page: "about:welcome", + }, + message_id: this.props.messageId, + }); + }; + if (document.readyState === "complete") { + // Page might have already triggered a load event because it waited for async data, + // e.g., attribution, so the dom load timing could be of a empty content + // with domState in telemetry captured as 'complete' + recordImpression(document.readyState); + } else { + window.addEventListener("load", () => recordImpression("load"), { + once: true, + }); + } + + // Captures user has seen about:welcome by setting + // firstrun.didSeeAboutWelcome pref to true and capturing welcome UI unique messageId + window.AWSendToParent("SET_WELCOME_MESSAGE_SEEN", this.props.messageId); + } + + handleStartBtnClick() { + AboutWelcomeUtils.handleUserAction(this.props.startButton.action); + const ping = { + event: "CLICK_BUTTON", + event_context: { + source: this.props.startButton.message_id, + page: "about:welcome", + }, + message_id: this.props.messageId, + id: "ABOUT_WELCOME", + }; + window.AWSendEventTelemetry(ping); + } + + render() { + const { props } = this; + if (props.template === "simplified") { + return ( + <SimpleAboutWelcome + metricsFlowUri={this.state.metricsFlowUri} + message_id={props.messageId} + utm_term={props.UTMTerm} + title={props.title} + subtitle={props.subtitle} + cards={props.cards} + startButton={props.startButton} + handleStartBtnClick={this.handleStartBtnClick} + /> + ); + } else if (props.template === "return_to_amo") { + return ( + <ReturnToAMO + message_id={props.messageId} + name={props.name} + url={props.url} + iconURL={props.iconURL} + /> + ); + } + + return ( + <MultiStageAboutWelcome + screens={props.screens} + metricsFlowUri={this.state.metricsFlowUri} + message_id={props.messageId} + utm_term={props.UTMTerm} + /> + ); + } +} + +AboutWelcome.defaultProps = DEFAULT_WELCOME_CONTENT; + +// Computes messageId and UTMTerm info used in telemetry +function ComputeTelemetryInfo(welcomeContent, experimentId, branchId) { + let messageId = + welcomeContent.template === "return_to_amo" + ? "RTAMO_DEFAULT_WELCOME" + : "DEFAULT_ABOUTWELCOME"; + let UTMTerm = "default"; + + if (welcomeContent.id) { + messageId = welcomeContent.id.toUpperCase(); + } + + if (experimentId && branchId) { + UTMTerm = `${experimentId}-${branchId}`.toLowerCase(); + } + return { + messageId, + UTMTerm, + }; +} + +async function retrieveRenderContent() { + // Check for override content in pref browser.aboutwelcome.overrideContent + let aboutWelcomeProps = await window.AWGetWelcomeOverrideContent(); + if (aboutWelcomeProps?.template) { + let { messageId, UTMTerm } = ComputeTelemetryInfo(aboutWelcomeProps); + return { aboutWelcomeProps, messageId, UTMTerm }; + } + + // Check for experiment and retrieve content + const { slug, branch } = await window.AWGetExperimentData(); + aboutWelcomeProps = branch?.feature ? branch.feature.value : {}; + + // Check if there is any attribution data, this could take a while to await in series + // especially when there is an add-on that requires remote lookup + // Moving RTAMO as part of another screen of multistage is one option to fix the delay + // as it will allow the initial page to be fast while we fetch attribution data in parallel for a later screen. + const attribution = await window.AWGetAttributionData(); + if (attribution?.template) { + aboutWelcomeProps = { + ...aboutWelcomeProps, + // If part of an experiment, render experiment template + template: aboutWelcomeProps?.template + ? aboutWelcomeProps.template + : attribution.template, + ...attribution.extraProps, + }; + } + + let { messageId, UTMTerm } = ComputeTelemetryInfo( + aboutWelcomeProps, + slug, + branch && branch.slug + ); + return { aboutWelcomeProps, messageId, UTMTerm }; +} + +async function mount() { + let { aboutWelcomeProps, messageId, UTMTerm } = await retrieveRenderContent(); + ReactDOM.render( + <AboutWelcome + messageId={messageId} + UTMTerm={UTMTerm} + {...aboutWelcomeProps} + />, + document.getElementById("root") + ); +} + +performance.mark("mount"); +mount(); |