blob: 3bffc5ce86913cddd1848ae7e91d78e64d9ebbea [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'chrome://resources/cr_elements/cr_hidden_style.css.js';
import './strings.m.js';
import {ClickInfo, Command} from 'chrome://resources/js/browser_command.mojom-webui.js';
import {BrowserCommandProxy} from 'chrome://resources/js/browser_command/browser_command_proxy.js';
import {EventTracker} from 'chrome://resources/js/event_tracker.js';
import {isChromeOS} from 'chrome://resources/js/platform.js';
import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {getTemplate} from './whats_new_app.html.js';
import {WhatsNewProxyImpl} from './whats_new_proxy.js';
interface CommandData {
commandId: number;
clickInfo: ClickInfo;
}
// TODO (https://www.crbug.com/1219381): Add some additional parameters so
// that we can filter the messages a bit better.
interface BrowserCommandMessageData {
data: CommandData;
}
export class WhatsNewAppElement extends PolymerElement {
static get is() {
return 'whats-new-app';
}
static get template() {
return getTemplate();
}
static get properties() {
return {
url_: {
type: String,
value: '',
},
};
}
private url_: string;
private isAutoOpen_: boolean = false;
private eventTracker_: EventTracker = new EventTracker();
constructor() {
super();
const queryParams = new URLSearchParams(window.location.search);
this.isAutoOpen_ = queryParams.has('auto');
// There are no subpages in What's New. Also remove the query param here
// since its value is recorded.
window.history.replaceState(undefined /* stateObject */, '', '/');
}
override connectedCallback() {
super.connectedCallback();
WhatsNewProxyImpl.getInstance().initialize().then(
url => this.handleUrlResult_(url));
}
override disconnectedCallback() {
super.disconnectedCallback();
this.eventTracker_.removeAll();
}
/**
* Handles the URL result of sending the initialize WebUI message.
* @param url The What's New URL to use in the iframe.
*/
private handleUrlResult_(url: string|null) {
if (!url) {
// This occurs in the special case of tests where we don't want to load
// remote content.
return;
}
const latest = this.isAutoOpen_ && !isChromeOS ? 'true' : 'false';
url += url.includes('?') ? '&' : '?';
this.url_ = url.concat(`latest=${latest}`);
this.eventTracker_.add(
window, 'message',
(event: Event) => this.handleMessage_(event as MessageEvent));
}
private handleMessage_(event: MessageEvent) {
if (!this.url_) {
return;
}
const {data, origin} = event;
const iframeUrl = new URL(this.url_);
if (!data || origin !== iframeUrl.origin) {
return;
}
const commandData = (data as BrowserCommandMessageData).data;
if (!commandData) {
return;
}
const commandId = Object.values(Command).includes(commandData.commandId) ?
commandData.commandId :
Command.kUnknownCommand;
const handler = BrowserCommandProxy.getInstance().handler;
handler.canExecuteCommand(commandId).then(({canExecute}) => {
if (canExecute) {
handler.executeCommand(commandId, commandData.clickInfo);
} else {
console.warn('Received invalid command: ' + commandId);
}
});
}
}
customElements.define(WhatsNewAppElement.is, WhatsNewAppElement);