blob: 93d017950640011d225d724ec728746360faf8c3 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Handles page loading sounds based on automation events.
*/
import {AutomationUtil} from '../../common/automation_util.js';
import {Earcon} from '../common/abstract_earcons.js';
import {ChromeVoxEvent} from '../common/custom_automation_event.js';
import {BaseAutomationHandler} from './base_automation_handler.js';
import {ChromeVox} from './chromevox.js';
import {ChromeVoxState, ChromeVoxStateObserver} from './chromevox_state.js';
const ActionType = chrome.automation.ActionType;
const AutomationNode = chrome.automation.AutomationNode;
const Dir = constants.Dir;
const EventType = chrome.automation.EventType;
const RoleType = chrome.automation.RoleType;
const StateType = chrome.automation.StateType;
/** @implements {ChromeVoxStateObserver} */
export class PageLoadSoundHandler extends BaseAutomationHandler {
/** @private */
constructor() {
super(null);
/** @private {boolean} */
this.didRequestLoadSound_ = false;
chrome.automation.getDesktop(desktop => {
this.node_ = desktop;
this.addListener_(EventType.LOAD_COMPLETE, this.onLoadComplete);
this.addListener_(EventType.LOAD_START, this.onLoadStart);
ChromeVoxState.addObserver(this);
});
}
static init() {
if (PageLoadSoundHandler.instance) {
throw 'Error: Trying to create two instances of singleton PageLoadSoundHandler';
}
PageLoadSoundHandler.instance = new PageLoadSoundHandler();
}
/**
* Stops page load sound on load complete.
* @param {!ChromeVoxEvent} evt
*/
onLoadComplete(evt) {
// We are only interested in load completes on valid top level roots.
const top = AutomationUtil.getTopLevelRoot(evt.target);
if (!top || top !== evt.target.root || !top.docUrl) {
return;
}
if (this.didRequestLoadSound_ && top.parent && top.parent.state.focused) {
ChromeVox.earcons.playEarcon(Earcon.PAGE_FINISH_LOADING);
this.didRequestLoadSound_ = false;
}
}
/**
* Starts page load sound on load start.
* @param {!ChromeVoxEvent} evt
*/
onLoadStart(evt) {
// We are only interested in load starts on focused top level roots.
const top = AutomationUtil.getTopLevelRoot(evt.target);
if (top && top === evt.target.root && top.docUrl && top.parent &&
top.parent.state.focused) {
ChromeVox.earcons.playEarcon(Earcon.PAGE_START_LOADING);
this.didRequestLoadSound_ = true;
}
}
/** @override */
onCurrentRangeChanged(range) {
if (!range || !range.start || !range.start.node) {
return;
}
const top = AutomationUtil.getTopLevelRoot(range.start.node);
// |top| might be undefined e.g. if range is not in a root web area.
if (this.didRequestLoadSound_ && (!top || top.docLoadingProgress === 1)) {
ChromeVox.earcons.playEarcon(Earcon.PAGE_FINISH_LOADING);
this.didRequestLoadSound_ = false;
}
// Note that we intentionally don't re-start progress playback here even if
// the docLoadingProgress < 1.
}
}
/** @type {PageLoadSoundHandler} */
PageLoadSoundHandler.instance;