diff --git a/build-system/tasks/presubmit-checks.js b/build-system/tasks/presubmit-checks.js index 2f5f75f9e012..8e587a84544f 100644 --- a/build-system/tasks/presubmit-checks.js +++ b/build-system/tasks/presubmit-checks.js @@ -449,6 +449,7 @@ const forbiddenTerms = { 'src/error.js', 'src/utils/xhr-utils.js', 'src/service/viewer-impl.js', + 'src/service/viewer-interface.js', 'src/service/viewer-cid-api.js', 'src/inabox/inabox-viewer.js', 'src/service/cid-impl.js', @@ -555,6 +556,7 @@ const forbiddenTerms = { 'src/3p-frame.js', 'src/iframe-attributes.js', 'src/service/viewer-impl.js', + 'src/service/viewer-interface.js', 'src/inabox/inabox-viewer.js', ], }, diff --git a/extensions/amp-access/0.1/amp-access-server-jwt.js b/extensions/amp-access/0.1/amp-access-server-jwt.js index 2229f59dd197..790665eeef6b 100644 --- a/extensions/amp-access/0.1/amp-access-server-jwt.js +++ b/extensions/amp-access/0.1/amp-access-server-jwt.js @@ -89,7 +89,7 @@ export class AccessServerJwtAdapter { /** @private @const */ this.clientAdapter_ = new AccessClientAdapter(ampdoc, configJson, context); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @const @private {!../../../src/service/xhr-impl.Xhr} */ diff --git a/extensions/amp-access/0.1/amp-access-server.js b/extensions/amp-access/0.1/amp-access-server.js index 5ff65a44361c..1907cb4b3dee 100644 --- a/extensions/amp-access/0.1/amp-access-server.js +++ b/extensions/amp-access/0.1/amp-access-server.js @@ -72,7 +72,7 @@ export class AccessServerAdapter { /** @private @const */ this.clientAdapter_ = new AccessClientAdapter(ampdoc, configJson, context); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @const @protected {!../../../src/service/xhr-impl.Xhr} */ diff --git a/extensions/amp-access/0.1/amp-access.js b/extensions/amp-access/0.1/amp-access.js index edc4568c497e..bfa71491b17a 100644 --- a/extensions/amp-access/0.1/amp-access.js +++ b/extensions/amp-access/0.1/amp-access.js @@ -83,7 +83,7 @@ export class AccessService { /** @private @const {!Promise} */ this.cid_ = Services.cidForDoc(ampdoc); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @private @const {!../../../src/service/viewport/viewport-interface.ViewportInterface} */ diff --git a/extensions/amp-access/0.1/login-dialog.js b/extensions/amp-access/0.1/login-dialog.js index 01cca77c91e2..9818715db475 100644 --- a/extensions/amp-access/0.1/login-dialog.js +++ b/extensions/amp-access/0.1/login-dialog.js @@ -70,11 +70,11 @@ export function getLoginUrl(ampdoc, urlOrPromise) { */ class ViewerLoginDialog { /** - * @param {!../../../src/service/viewer-impl.Viewer} viewer + * @param {!../../../src/service/viewer-interface.ViewerInterface} viewer * @param {string|!Promise} urlOrPromise */ constructor(viewer, urlOrPromise) { - /** @const {!../../../src/service/viewer-impl.Viewer} */ + /** @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer = viewer; /** @const {string|!Promise} */ @@ -122,14 +122,14 @@ class ViewerLoginDialog { export class WebLoginDialog { /** * @param {!Window} win - * @param {!../../../src/service/viewer-impl.Viewer} viewer + * @param {!../../../src/service/viewer-interface.ViewerInterface} viewer * @param {string|!Promise} urlOrPromise */ constructor(win, viewer, urlOrPromise) { /** @const {!Window} */ this.win = win; - /** @const {!../../../src/service/viewer-impl.Viewer} */ + /** @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer = viewer; /** @const {string|!Promise} */ diff --git a/extensions/amp-ad/0.1/amp-ad-xorigin-iframe-handler.js b/extensions/amp-ad/0.1/amp-ad-xorigin-iframe-handler.js index 1493af7e9eff..007a94e4d9cc 100644 --- a/extensions/amp-ad/0.1/amp-ad-xorigin-iframe-handler.js +++ b/extensions/amp-ad/0.1/amp-ad-xorigin-iframe-handler.js @@ -75,7 +75,7 @@ export class AmpAdXOriginIframeHandler { /** @private {!Array} functions to unregister listeners */ this.unlisteners_ = []; - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.baseInstance_.getAmpDoc()); /** @private @const {!../../../src/service/viewport/viewport-interface.ViewportInterface} */ diff --git a/extensions/amp-analytics/0.1/activity-impl.js b/extensions/amp-analytics/0.1/activity-impl.js index 3d8a760f9370..b125296903a5 100644 --- a/extensions/amp-analytics/0.1/activity-impl.js +++ b/extensions/amp-analytics/0.1/activity-impl.js @@ -189,7 +189,7 @@ export class Activity { /** @private @const {!ActivityHistory} */ this.activityHistory_ = new ActivityHistory(); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc); /** @private @const {!../../../src/service/viewport/viewport-interface.ViewportInterface} */ diff --git a/extensions/amp-analytics/0.1/analytics-root.js b/extensions/amp-analytics/0.1/analytics-root.js index 03a3b1b34300..abfebf651ec1 100644 --- a/extensions/amp-analytics/0.1/analytics-root.js +++ b/extensions/amp-analytics/0.1/analytics-root.js @@ -130,7 +130,7 @@ export class AnalyticsRoot { /** * The viewer of analytics root - * @return {!../../../src/service/viewer-impl.Viewer} + * @return {!../../../src/service/viewer-interface.ViewerInterface} */ getViewer() { return Services.viewerForDoc(this.ampdoc); diff --git a/extensions/amp-app-banner/0.1/amp-app-banner.js b/extensions/amp-app-banner/0.1/amp-app-banner.js index 676dedc35ffe..aa9ec52e801a 100644 --- a/extensions/amp-app-banner/0.1/amp-app-banner.js +++ b/extensions/amp-app-banner/0.1/amp-app-banner.js @@ -209,7 +209,7 @@ export class AmpIosAppBanner extends AbstractAppBanner { constructor(element) { super(element); - /** @private {?../../../src/service/viewer-impl.Viewer} */ + /** @private {?../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = null; /** @private {?Element} */ diff --git a/extensions/amp-bind/0.1/bind-impl.js b/extensions/amp-bind/0.1/bind-impl.js index 835625940903..96d22b104927 100644 --- a/extensions/amp-bind/0.1/bind-impl.js +++ b/extensions/amp-bind/0.1/bind-impl.js @@ -209,7 +209,7 @@ export class Bind { /** @private {?./bind-validator.BindValidator} */ this.validator_ = null; - /** @const @private {!../../../src/service/viewer-impl.Viewer} */ + /** @const @private {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc); this.viewer_.onMessageRespond('premutate', this.premutate_.bind(this)); diff --git a/extensions/amp-consent/0.1/consent-ui.js b/extensions/amp-consent/0.1/consent-ui.js index 6c30e6cec7b4..6ffde093c09b 100644 --- a/extensions/amp-consent/0.1/consent-ui.js +++ b/extensions/amp-consent/0.1/consent-ui.js @@ -99,7 +99,7 @@ export class ConsentUI { /** @private {!../../../src/service/viewport/viewport-interface.ViewportInterface} */ this.viewport_ = Services.viewportForDoc(this.ampdoc_); - /** @private {?../../../src/service/viewer-impl.Viewer} */ + /** @private {?../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc_); /** @private {!Element} */ diff --git a/extensions/amp-experiment/1.0/variant.js b/extensions/amp-experiment/1.0/variant.js index 75c41bb5d2d9..dc0a4e669cd3 100644 --- a/extensions/amp-experiment/1.0/variant.js +++ b/extensions/amp-experiment/1.0/variant.js @@ -71,7 +71,7 @@ export class Variants { * Allocates the current page view to an experiment variant based on the given * experiment from the config. * @param {!../../../src/service/ampdoc-impl.AmpDoc} ampdoc - * @param {!../../../src/service/viewer-impl.Viewer} viewer + * @param {!../../../src/service/viewer-interface.ViewerInterface} viewer * @param {string} experimentName * @param {!JsonObject} experimentObject * @return {!Promise} diff --git a/extensions/amp-form/0.1/amp-form.js b/extensions/amp-form/0.1/amp-form.js index b471f7166126..b9de0e0d7778 100644 --- a/extensions/amp-form/0.1/amp-form.js +++ b/extensions/amp-form/0.1/amp-form.js @@ -146,7 +146,7 @@ export class AmpForm { /** @const @private {!../../../src/service/resources-impl.ResourcesDef} */ this.resources_ = Services.resourcesForDoc(this.form_); - /** @const @private {!../../../src/service/viewer-impl.Viewer} */ + /** @const @private {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.form_); /** diff --git a/extensions/amp-fx-collection/0.1/amp-fx-collection.js b/extensions/amp-fx-collection/0.1/amp-fx-collection.js index 7ac326f6ccc8..676cb1485ee7 100644 --- a/extensions/amp-fx-collection/0.1/amp-fx-collection.js +++ b/extensions/amp-fx-collection/0.1/amp-fx-collection.js @@ -48,7 +48,7 @@ export class AmpFxCollection { /** @private @const {!Array} */ this.seen_ = []; - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); Promise.all([ampdoc.whenReady(), this.viewer_.whenFirstVisible()]).then( diff --git a/extensions/amp-live-list/0.1/live-list-manager.js b/extensions/amp-live-list/0.1/live-list-manager.js index f67b6edf2569..e7a549d36cd6 100644 --- a/extensions/amp-live-list/0.1/live-list-manager.js +++ b/extensions/amp-live-list/0.1/live-list-manager.js @@ -53,7 +53,7 @@ export class LiveListManager { /** @private @const {!Object} */ this.liveLists_ = Object.create(null); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc); /** @private @const {!../../../src/service/extensions-impl.Extensions} */ diff --git a/extensions/amp-skimlinks/0.1/amp-skimlinks.js b/extensions/amp-skimlinks/0.1/amp-skimlinks.js index 9cb3e530b566..9bb630436563 100644 --- a/extensions/amp-skimlinks/0.1/amp-skimlinks.js +++ b/extensions/amp-skimlinks/0.1/amp-skimlinks.js @@ -44,7 +44,7 @@ export class AmpSkimlinks extends AMP.BaseElement { /** @private {?../../../src/service/document-info-impl.DocumentInfoDef} */ this.docInfo_ = null; - /** @private {?../../../src/service/viewer-impl.Viewer} */ + /** @private {?../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = null; /** @private {?./link-rewriter/link-rewriter-manager.LinkRewriterManager} */ diff --git a/extensions/amp-social-share/0.1/amp-social-share.js b/extensions/amp-social-share/0.1/amp-social-share.js index af0ac087e669..612a09ab1649 100644 --- a/extensions/amp-social-share/0.1/amp-social-share.js +++ b/extensions/amp-social-share/0.1/amp-social-share.js @@ -39,7 +39,7 @@ class AmpSocialShare extends AMP.BaseElement { /** @private {?../../../src/service/platform-impl.Platform} */ this.platform_ = null; - /** @private {?../../../src/service/viewer-impl.Viewer} */ + /** @private {?../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = null; /** @private {?string} */ diff --git a/extensions/amp-story/0.1/amp-story-info-dialog.js b/extensions/amp-story/0.1/amp-story-info-dialog.js index 52c7c7a42c89..a0382cf137be 100644 --- a/extensions/amp-story/0.1/amp-story-info-dialog.js +++ b/extensions/amp-story/0.1/amp-story-info-dialog.js @@ -69,7 +69,7 @@ export class InfoDialog { /** @private {?Element} */ this.moreInfoLinkEl_ = null; - /** @const @private {!../../../src/service/viewer-impl.Viewer} */ + /** @const @private {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.parentEl_); } diff --git a/extensions/amp-story/1.0/amp-story-info-dialog.js b/extensions/amp-story/1.0/amp-story-info-dialog.js index a0909d72f494..a9ff58532619 100644 --- a/extensions/amp-story/1.0/amp-story-info-dialog.js +++ b/extensions/amp-story/1.0/amp-story-info-dialog.js @@ -73,7 +73,7 @@ export class InfoDialog { /** @private {?Element} */ this.moreInfoLinkEl_ = null; - /** @const @private {!../../../src/service/viewer-impl.Viewer} */ + /** @const @private {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.parentEl_); } diff --git a/extensions/amp-story/1.0/amp-story.js b/extensions/amp-story/1.0/amp-story.js index 5eb4b153c1a9..0b995783d527 100644 --- a/extensions/amp-story/1.0/amp-story.js +++ b/extensions/amp-story/1.0/amp-story.js @@ -332,7 +332,7 @@ export class AmpStory extends AMP.BaseElement { /** @private @const {!../../../src/service/platform-impl.Platform} */ this.platform_ = Services.platformFor(this.win); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.element); /** diff --git a/extensions/amp-subscriptions-google/0.1/amp-subscriptions-google.js b/extensions/amp-subscriptions-google/0.1/amp-subscriptions-google.js index c22f4af626ea..a8fd59fc3aa1 100644 --- a/extensions/amp-subscriptions-google/0.1/amp-subscriptions-google.js +++ b/extensions/amp-subscriptions-google/0.1/amp-subscriptions-google.js @@ -414,7 +414,7 @@ export class GoogleSubscriptionsPlatform { } /** - * @param {!../../../src/service/viewer-impl.Viewer} viewer + * @param {!../../../src/service/viewer-interface.ViewerInterface} viewer * @private */ resolveGoogleViewer_(viewer) { diff --git a/extensions/amp-subscriptions/0.1/amp-subscriptions.js b/extensions/amp-subscriptions/0.1/amp-subscriptions.js index 29e39e21d018..bc25abaf2630 100644 --- a/extensions/amp-subscriptions/0.1/amp-subscriptions.js +++ b/extensions/amp-subscriptions/0.1/amp-subscriptions.js @@ -98,7 +98,7 @@ export class SubscriptionService { /** @private {!ViewerTracker} */ this.viewerTracker_ = new ViewerTracker(ampdoc); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @private {?Promise} */ diff --git a/extensions/amp-subscriptions/0.1/viewer-subscription-platform.js b/extensions/amp-subscriptions/0.1/viewer-subscription-platform.js index f31d61e92523..ccf659e438b0 100644 --- a/extensions/amp-subscriptions/0.1/viewer-subscription-platform.js +++ b/extensions/amp-subscriptions/0.1/viewer-subscription-platform.js @@ -51,7 +51,7 @@ export class ViewerSubscriptionPlatform { serviceAdapter ); - /** @const @private {!../../../src/service/viewer-impl.Viewer} */ + /** @const @private {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc_); this.viewer_.onMessage( 'subscriptionchange', diff --git a/extensions/amp-subscriptions/0.1/viewer-tracker.js b/extensions/amp-subscriptions/0.1/viewer-tracker.js index cabf63dd05c9..4ebfa89ea0bd 100644 --- a/extensions/amp-subscriptions/0.1/viewer-tracker.js +++ b/extensions/amp-subscriptions/0.1/viewer-tracker.js @@ -29,7 +29,7 @@ export class ViewerTracker { /** @private */ this.ampdoc_ = ampdoc; - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @private {?Promise} */ diff --git a/extensions/amp-user-notification/0.1/amp-user-notification.js b/extensions/amp-user-notification/0.1/amp-user-notification.js index e85e22dc403f..2b95677c8f3a 100644 --- a/extensions/amp-user-notification/0.1/amp-user-notification.js +++ b/extensions/amp-user-notification/0.1/amp-user-notification.js @@ -472,7 +472,7 @@ export class UserNotificationManager { /** @private @const {!Object} */ this.deferRegistry_ = Object.create(null); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc); /** @private @const {!Promise} */ diff --git a/extensions/amp-viewer-assistance/0.1/amp-viewer-assistance.js b/extensions/amp-viewer-assistance/0.1/amp-viewer-assistance.js index f2ae71710e0e..fe752fd4107a 100644 --- a/extensions/amp-viewer-assistance/0.1/amp-viewer-assistance.js +++ b/extensions/amp-viewer-assistance/0.1/amp-viewer-assistance.js @@ -60,7 +60,7 @@ export class AmpViewerAssistance { ); }); - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @private @const {!../../../src/service/action-impl.ActionService} */ diff --git a/extensions/amp-viewer-integration/0.1/amp-viewer-integration.js b/extensions/amp-viewer-integration/0.1/amp-viewer-integration.js index 81db2a61a62f..dbed32975317 100644 --- a/extensions/amp-viewer-integration/0.1/amp-viewer-integration.js +++ b/extensions/amp-viewer-integration/0.1/amp-viewer-integration.js @@ -178,7 +178,7 @@ export class AmpViewerIntegration { } /** - * @param {!../../../src/service/viewer-impl.Viewer} viewer + * @param {!../../../src/service/viewer-interface.ViewerInterface} viewer * @param {!../../../src/service/ampdoc-impl.AmpDoc} ampdoc * @param {string} origin * @param {!Messaging} messaging @@ -206,7 +206,7 @@ export class AmpViewerIntegration { /** * @param {!Messaging} messaging - * @param {!../../../src/service/viewer-impl.Viewer} viewer + * @param {!../../../src/service/viewer-interface.ViewerInterface} viewer * @param {string} origin * @return {Promise<*>|undefined} * @private diff --git a/extensions/amp-viewer-integration/0.1/highlight-handler.js b/extensions/amp-viewer-integration/0.1/highlight-handler.js index 454642f46a40..46f009212442 100644 --- a/extensions/amp-viewer-integration/0.1/highlight-handler.js +++ b/extensions/amp-viewer-integration/0.1/highlight-handler.js @@ -142,7 +142,7 @@ export class HighlightHandler { constructor(ampdoc, highlightInfo) { /** @private @const {!../../../src/service/ampdoc-impl.AmpDoc} */ this.ampdoc_ = ampdoc; - /** @private @const {!../../../src/service/viewer-impl.Viewer} */ + /** @private @const {!../../../src/service/viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @private @const {!../../../src/service/viewport/viewport-interface.ViewportInterface} */ this.viewport_ = Services.viewportForDoc(this.ampdoc_); diff --git a/src/chunk.js b/src/chunk.js index 67cacc877eaa..7a5aad6fa1d5 100644 --- a/src/chunk.js +++ b/src/chunk.js @@ -335,9 +335,9 @@ class Chunks { } }); - /** @private @const {!Promise} */ + /** @private @const {!Promise} */ this.viewerPromise_ = Services.viewerPromiseForDoc(ampDoc); - /** @protected {?./service/viewer-impl.Viewer} */ + /** @protected {?./service/viewer-interface.ViewerInterface} */ this.viewer = null; this.viewerPromise_.then(viewer => { this.viewer = viewer; diff --git a/src/service/cache-cid-api.js b/src/service/cache-cid-api.js index 1b844c2c946d..72cc1ecd09c5 100644 --- a/src/service/cache-cid-api.js +++ b/src/service/cache-cid-api.js @@ -52,7 +52,7 @@ export class CacheCidApi { /** @private {!./ampdoc-impl.AmpDoc} */ this.ampdoc_ = ampdoc; - /** @private {!./viewer-impl.Viewer} */ + /** @private {!./viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc_); /** @private {?Promise} */ diff --git a/src/service/history-impl.js b/src/service/history-impl.js index 28cbd182a3c8..4b1702e164bc 100644 --- a/src/service/history-impl.js +++ b/src/service/history-impl.js @@ -855,13 +855,13 @@ export class HistoryBindingNatural_ { export class HistoryBindingVirtual_ { /** * @param {!Window} win - * @param {!./viewer-impl.Viewer} viewer + * @param {!./viewer-interface.ViewerInterface} viewer */ constructor(win, viewer) { /** @const {!Window} */ this.win = win; - /** @private @const {!./viewer-impl.Viewer} */ + /** @private @const {!./viewer-interface.ViewerInterface} */ this.viewer_ = viewer; /** @private {number} */ diff --git a/src/service/navigation.js b/src/service/navigation.js index 5766879f3095..6d56e4f06108 100644 --- a/src/service/navigation.js +++ b/src/service/navigation.js @@ -107,7 +107,7 @@ export class Navigation { /** @private @const {!./viewport/viewport-interface.ViewportInterface} */ this.viewport_ = Services.viewportForDoc(this.ampdoc); - /** @private @const {!./viewer-impl.Viewer} */ + /** @private @const {!./viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc); /** @private @const {!./history-impl.History} */ diff --git a/src/service/performance-impl.js b/src/service/performance-impl.js index 6a1d759ea39a..7fc02ffabaab 100644 --- a/src/service/performance-impl.js +++ b/src/service/performance-impl.js @@ -83,7 +83,7 @@ export class Performance { /** @const @private {!Array} */ this.events_ = []; - /** @private {?./viewer-impl.Viewer} */ + /** @private {?./viewer-interface.ViewerInterface} */ this.viewer_ = null; /** @private {?./resources-impl.ResourcesDef} */ diff --git a/src/service/resources-impl.js b/src/service/resources-impl.js index 9b1c7c506c57..97759f381335 100644 --- a/src/service/resources-impl.js +++ b/src/service/resources-impl.js @@ -325,7 +325,7 @@ export class Resources { /** @const {!Window} */ this.win = ampdoc.win; - /** @const @private {!./viewer-impl.Viewer} */ + /** @const @private {!./viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(ampdoc); /** @private {boolean} */ diff --git a/src/service/storage-impl.js b/src/service/storage-impl.js index 1cd78ee8f13e..08d2dcbb7ea1 100644 --- a/src/service/storage-impl.js +++ b/src/service/storage-impl.js @@ -40,14 +40,14 @@ const MAX_VALUES_PER_ORIGIN = 8; export class Storage { /** * @param {!./ampdoc-impl.AmpDoc} ampdoc - * @param {!../service/viewer-impl.Viewer} viewer + * @param {!../service/viewer-interface.ViewerInterface} viewer * @param {!StorageBindingDef} binding */ constructor(ampdoc, viewer, binding) { /** @const {!./ampdoc-impl.AmpDoc} */ this.ampdoc = ampdoc; - /** @private @const {!../service/viewer-impl.Viewer} */ + /** @private @const {!../service/viewer-interface.ViewerInterface} */ this.viewer_ = viewer; /** @private @const {!StorageBindingDef} */ @@ -384,10 +384,10 @@ export class LocalStorageBinding { */ export class ViewerStorageBinding { /** - * @param {!../service/viewer-impl.Viewer} viewer + * @param {!../service/viewer-interface.ViewerInterface} viewer */ constructor(viewer) { - /** @private @const {!../service/viewer-impl.Viewer} */ + /** @private @const {!../service/viewer-interface.ViewerInterface} */ this.viewer_ = viewer; } diff --git a/src/service/viewer-cid-api.js b/src/service/viewer-cid-api.js index 1bfb4bc35b48..8a94e6601625 100644 --- a/src/service/viewer-cid-api.js +++ b/src/service/viewer-cid-api.js @@ -30,7 +30,7 @@ export class ViewerCidApi { /** @private {!./ampdoc-impl.AmpDoc} */ this.ampdoc_ = ampdoc; - /** @private {!./viewer-impl.Viewer} */ + /** @private {!./viewer-interface.ViewerInterface} */ this.viewer_ = Services.viewerForDoc(this.ampdoc_); const {canonicalUrl} = Services.documentInfoForDoc(this.ampdoc_); diff --git a/src/service/viewer-impl.js b/src/service/viewer-impl.js index 5c31504abfed..d87fb5c2bb98 100644 --- a/src/service/viewer-impl.js +++ b/src/service/viewer-impl.js @@ -17,6 +17,7 @@ import {Deferred, tryResolve} from '../utils/promise'; import {Observable} from '../observable'; import {Services} from '../services'; +import {ViewerInterface} from './viewer-interface'; import {VisibilityState} from '../visibility-state'; import {dev, devAssert, duplicateErrorIfNecessary} from '../log'; import {findIndex} from '../utils/array'; @@ -57,19 +58,15 @@ const VIEWER_ORIGIN_TIMEOUT_ = 1000; */ const TRIM_ORIGIN_PATTERN_ = /^(https?:\/\/)((www[0-9]*|web|ftp|wap|home|mobile|amp|m)\.)+/i; -/** - * @typedef {function(!JsonObject):(!Promise|undefined)} - */ -let RequestResponderDef; - /** * An AMP representation of the Viewer. This class doesn't do any work itself * but instead delegates everything to the actual viewer. This class and the * actual Viewer are connected via "AMP.viewer" using three methods: * {@link getParam}, {@link receiveMessage} and {@link setMessageDeliverer}. + * @implements {ViewerInterface} * @package Visible for type. */ -export class Viewer { +export class ViewerImpl { /** * @param {!./ampdoc-impl.AmpDoc} ampdoc */ @@ -95,7 +92,7 @@ export class Viewer { /** @private {!Object>} */ this.messageObservables_ = map(); - /** @private {!Object} */ + /** @private {!Object} */ this.messageResponders_ = map(); /** @private {!Observable} */ @@ -311,23 +308,17 @@ export class Viewer { }); } - /** - * Returns the value of a viewer's startup parameter with the specified - * name or "undefined" if the parameter wasn't defined at startup time. - * @param {string} name - * @return {?string} - * @export - */ + /** @override */ + getAmpDoc() { + return this.ampdoc; + } + + /** @override */ getParam(name) { return this.ampdoc.getParam(name); } - /** - * Viewers can communicate their "capabilities" and this method allows - * checking them. - * @param {string} name Of the capability. - * @return {boolean} - */ + /** @override */ hasCapability(name) { const capabilities = this.ampdoc.getParam('cap'); if (!capabilities) { @@ -337,26 +328,17 @@ export class Viewer { return capabilities.split(',').indexOf(name) != -1; } - /** - * Whether the document is embedded in a viewer. - * @return {boolean} - */ + /** @override */ isEmbedded() { return !!this.messagingReadyPromise_; } - /** - * Whether the document is embedded in a webview. - * @return {boolean} - */ + /** @override */ isWebviewEmbedded() { return !this.isIframed_ && this.ampdoc.getParam('webview') == '1'; } - /** - * Whether the document is embedded in a Chrome Custom Tab. - * @return {boolean} - */ + /** @override */ isCctEmbedded() { if (this.isCctEmbedded_ != null) { return this.isCctEmbedded_; @@ -371,18 +353,12 @@ export class Viewer { return this.isCctEmbedded_; } - /** - * Whether the document was served by a proxy. - * @return {boolean} - */ + /** @override */ isProxyOrigin() { return this.isProxyOrigin_; } - /** - * Update the URL fragment with data needed to support custom tabs. This will - * not clear query string parameters, but will clear the fragment. - */ + /** @override */ maybeUpdateFragmentForCct() { if (!this.isCctEmbedded()) { return; @@ -423,45 +399,29 @@ export class Viewer { return trimOrigin(first) == trimOrigin(second); } - /** - * @return {boolean} - */ + /** @override */ isRuntimeOn() { return this.isRuntimeOn_; } - /** - */ + /** @override */ toggleRuntime() { this.isRuntimeOn_ = !this.isRuntimeOn_; dev().fine(TAG_, 'Runtime state:', this.isRuntimeOn_); this.runtimeOnObservable_.fire(this.isRuntimeOn_); } - /** - * @param {function(boolean)} handler - * @return {!UnlistenDef} - */ + /** @override */ onRuntimeState(handler) { return this.runtimeOnObservable_.add(handler); } - /** - * Whether the viewer overtakes the history for AMP document. If yes, - * the viewer must implement history messages "pushHistory" and "popHistory" - * and emit message "historyPopped" - * @return {boolean} - */ + /** @override */ isOvertakeHistory() { return this.overtakeHistory_; } - /** - * Returns visibility state configured by the viewer. - * See {@link isVisible}. - * @return {!VisibilityState} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ getVisibilityState() { return this.ampdoc.getVisibilityState(); } @@ -492,83 +452,42 @@ export class Viewer { dev().fine(TAG_, 'visibilitychange event:', this.getVisibilityState()); } - /** - * Whether the AMP document currently visible. The reasons why it might not - * be visible include user switching to another tab, browser running the - * document in the prerender mode or viewer running the document in the - * prerender mode. - * @return {boolean} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ isVisible() { return this.ampdoc.isVisible(); } - /** - * Whether the AMP document has been ever visible before. Since the visiblity - * state of a document can be flipped back and forth we sometimes want to know - * if a document has ever been visible. - * @return {boolean} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ hasBeenVisible() { return this.ampdoc.getLastVisibleTime() != null; } - /** - * Returns a Promise that only ever resolved when the current - * AMP document first becomes visible. - * @return {!Promise} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ whenFirstVisible() { return this.ampdoc.whenFirstVisible(); } - /** - * Returns a Promise that resolve when current doc becomes visible. - * The promise resolves immediately if doc is already visible. - * @return {!Promise} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ whenNextVisible() { return this.ampdoc.whenNextVisible(); } - /** - * Returns the time when the document has become visible for the first time. - * If document has not yet become visible, the returned value is `null`. - * @return {?time} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ getFirstVisibleTime() { return this.ampdoc.getFirstVisibleTime(); } - /** - * Returns the time when the document has become visible for the last time. - * If document has not yet become visible, the returned value is `null`. - * @return {?time} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ getLastVisibleTime() { return this.ampdoc.getLastVisibleTime(); } - /** - * How much the viewer has requested the runtime to prerender the document. - * The values are in number of screens. - * @return {number} - */ + /** @override */ getPrerenderSize() { return this.prerenderSize_; } - /** - * Returns the resolved viewer URL value. It's by default the current page's - * URL. The trusted viewers are allowed to override this value. - * @return {string} - */ + /** @override */ getResolvedViewerUrl() { return this.resolvedViewerUrl_; } @@ -584,40 +503,22 @@ export class Viewer { return this.viewerUrl_; } - /** - * Possibly return the messaging origin if set. This would be the origin - * of the parent viewer. - * @return {?string} - */ + /** @override */ maybeGetMessagingOrigin() { return this.messagingOrigin_; } - /** - * Returns an unconfirmed "referrer" URL that can be optionally customized by - * the viewer. Consider using `getReferrerUrl()` instead, which returns the - * promise that will yield the confirmed "referrer" URL. - * @return {string} - */ + /** @override */ getUnconfirmedReferrerUrl() { return this.unconfirmedReferrerUrl_; } - /** - * Returns the promise that will yield the confirmed "referrer" URL. This - * URL can be optionally customized by the viewer, but viewer is required - * to be a trusted viewer. - * @return {!Promise} - */ + /** @override */ getReferrerUrl() { return this.referrerUrl_; } - /** - * Whether the viewer has been whitelisted for more sensitive operations - * such as customizing referrer. - * @return {!Promise} - */ + /** @override */ isTrustedViewer() { if (!this.isTrustedViewer_) { const isTrustedAncestorOrigins = this.isTrustedAncestorOrigins_(); @@ -655,12 +556,7 @@ export class Viewer { } } - /** - * Returns the promise that resolves to URL representing the origin of the - * viewer. If the document is not embedded or if a viewer origin can't be - * found, empty string is returned. - * @return {!Promise} - */ + /** @override */ getViewerOrigin() { if (!this.viewerOrigin_) { let origin; @@ -706,24 +602,12 @@ export class Viewer { return urls.trustedViewerHosts.some(th => th.test(url.hostname)); } - /** - * Adds a "visibilitychange" event listener for viewer events. The - * callback can check {@link isVisible} and {@link getPrefetchCount} - * methods for more info. - * @param {function()} handler - * @return {!UnlistenDef} - * TODO(#22733): deprecate/remove when ampdoc-fie is launched. - */ + /** @override */ onVisibilityChanged(handler) { return this.ampdoc.onVisibilityChanged(handler); } - /** - * Adds a eventType listener for viewer events. - * @param {string} eventType - * @param {function(!JsonObject)} handler - * @return {!UnlistenDef} - */ + /** @override */ onMessage(eventType, handler) { let observable = this.messageObservables_[eventType]; if (!observable) { @@ -733,12 +617,7 @@ export class Viewer { return observable.add(handler); } - /** - * Adds a eventType listener for viewer events. - * @param {string} eventType - * @param {!RequestResponderDef} responder - * @return {!UnlistenDef} - */ + /** @override */ onMessageRespond(eventType, responder) { this.messageResponders_[eventType] = responder; return () => { @@ -748,14 +627,7 @@ export class Viewer { }; } - /** - * Requests AMP document to receive a message from Viewer. - * @param {string} eventType - * @param {!JsonObject} data - * @param {boolean} unusedAwaitResponse - * @return {(!Promise<*>|undefined)} - * @export - */ + /** @override */ receiveMessage(eventType, data, unusedAwaitResponse) { if (eventType == 'visibilitychange') { if (data['prerenderSize'] !== undefined) { @@ -785,14 +657,7 @@ export class Viewer { return undefined; } - /** - * Provides a message delivery mechanism by which AMP document can send - * messages to the viewer. - * @param {function(string, (?JsonObject|string|undefined), boolean): - * (!Promise<*>|undefined)} deliverer - * @param {string} origin - * @export - */ + /** @override */ setMessageDeliverer(deliverer, origin) { if (this.messageDeliverer_) { throw new Error('message channel can only be initialized once'); @@ -822,33 +687,12 @@ export class Viewer { } } - /** - * Sends the message to the viewer without waiting for any response. - * If cancelUnsent is true, the previous message of the same message type will - * be canceled. - * - * This is a restricted API. - * - * @param {string} eventType - * @param {?JsonObject|string|undefined} data - * @param {boolean=} cancelUnsent - */ + /** @override */ sendMessage(eventType, data, cancelUnsent = false) { this.sendMessageInternal_(eventType, data, cancelUnsent, false); } - /** - * Sends the message to the viewer and wait for response. - * If cancelUnsent is true, the previous message of the same message type will - * be canceled. - * - * This is a restricted API. - * - * @param {string} eventType - * @param {?JsonObject|string|undefined} data - * @param {boolean=} cancelUnsent - * @return {!Promise<(?JsonObject|string|undefined)>} the response promise - */ + /** @override */ sendMessageAwaitResponse(eventType, data, cancelUnsent = false) { return this.sendMessageInternal_(eventType, data, cancelUnsent, true); } @@ -914,14 +758,7 @@ export class Viewer { return message.responsePromise; } - /** - * Broadcasts a message to all other AMP documents under the same viewer. It - * will attempt to deliver messages when the messaging channel has been - * established, but it will not fail if the channel is timed out. - * - * @param {!JsonObject} message - * @return {!Promise} a Promise of success or not - */ + /** @override */ broadcast(message) { if (!this.messagingReadyPromise_) { // Messaging is not expected. @@ -934,30 +771,17 @@ export class Viewer { ); } - /** - * Registers receiver for the broadcast events. - * @param {function(!JsonObject)} handler - * @return {!UnlistenDef} - */ + /** @override */ onBroadcast(handler) { return this.broadcastObservable_.add(handler); } - /** - * Resolves when there is a messaging channel established with the viewer. - * Will be null if no messaging is needed like in an non-embedded document. - * Deprecated: do not use. sendMessage and sendMessageAwaitResponse already - * wait for messaging channel ready. - * @return {?Promise} - */ + /** @override */ whenMessagingReady() { return this.messagingReadyPromise_; } - /** - * Replace the document url with the viewer provided new replaceUrl. - * @param {?string} newUrl - */ + /** @override */ replaceUrl(newUrl) { if ( !newUrl || @@ -1008,7 +832,7 @@ export function installViewerServiceForDoc(ampdoc) { registerServiceBuilderForDoc( ampdoc, 'viewer', - Viewer, + ViewerImpl, /* opt_instantiate */ true ); } diff --git a/src/service/viewer-interface.js b/src/service/viewer-interface.js new file mode 100644 index 000000000000..f9cccbf667dd --- /dev/null +++ b/src/service/viewer-interface.js @@ -0,0 +1,318 @@ +/** + * Copyright 2019 The AMP HTML Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS-IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @typedef {function(!JsonObject):(!Promise|undefined)} + */ +export let RequestResponderDef; + +/* eslint-disable no-unused-vars */ +/** + * @interface + */ +export class ViewerInterface { + /** + * @return {!./ampdoc-impl.AmpDoc} + */ + getAmpDoc() {} + + /** + * Returns the value of a viewer's startup parameter with the specified + * name or "undefined" if the parameter wasn't defined at startup time. + * @param {string} name + * @return {?string} + * @export + */ + getParam(name) {} + + /** + * Viewers can communicate their "capabilities" and this method allows + * checking them. + * @param {string} name Of the capability. + * @return {boolean} + */ + hasCapability(name) {} + + /** + * Whether the document is embedded in a viewer. + * @return {boolean} + */ + isEmbedded() {} + + /** + * Whether the document is embedded in a webview. + * @return {boolean} + */ + isWebviewEmbedded() {} + + /** + * Whether the document is embedded in a Chrome Custom Tab. + * @return {boolean} + */ + isCctEmbedded() {} + + /** + * Whether the document was served by a proxy. + * @return {boolean} + */ + isProxyOrigin() {} + + /** + * Update the URL fragment with data needed to support custom tabs. This will + * not clear query string parameters, but will clear the fragment. + */ + maybeUpdateFragmentForCct() {} + + /** + * @return {boolean} + */ + isRuntimeOn() {} + + /** + */ + toggleRuntime() {} + + /** + * @param {function(boolean)} handler + * @return {!UnlistenDef} + */ + onRuntimeState(handler) {} + + /** + * Whether the viewer overtakes the history for AMP document. If yes, + * the viewer must implement history messages "pushHistory" and "popHistory" + * and emit message "historyPopped" + * @return {boolean} + */ + isOvertakeHistory() {} + + /** + * Returns visibility state configured by the viewer. + * See {@link isVisible}. + * @return {!../visibility-state.VisibilityState} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + getVisibilityState() {} + + /** + * Whether the AMP document currently visible. The reasons why it might not + * be visible include user switching to another tab, browser running the + * document in the prerender mode or viewer running the document in the + * prerender mode. + * @return {boolean} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + isVisible() {} + + /** + * Whether the AMP document has been ever visible before. Since the visiblity + * state of a document can be flipped back and forth we sometimes want to know + * if a document has ever been visible. + * @return {boolean} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + hasBeenVisible() {} + + /** + * Returns a Promise that only ever resolved when the current + * AMP document first becomes visible. + * @return {!Promise} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + whenFirstVisible() {} + + /** + * Returns a Promise that resolve when current doc becomes visible. + * The promise resolves immediately if doc is already visible. + * @return {!Promise} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + whenNextVisible() {} + + /** + * Returns the time when the document has become visible for the first time. + * If document has not yet become visible, the returned value is `null`. + * @return {?time} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + getFirstVisibleTime() {} + + /** + * Returns the time when the document has become visible for the last time. + * If document has not yet become visible, the returned value is `null`. + * @return {?time} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + getLastVisibleTime() {} + + /** + * How much the viewer has requested the runtime to prerender the document. + * The values are in number of screens. + * @return {number} + */ + getPrerenderSize() {} + + /** + * Returns the resolved viewer URL value. It's by default the current page's + * URL. The trusted viewers are allowed to override this value. + * @return {string} + */ + getResolvedViewerUrl() {} + + /** + * Possibly return the messaging origin if set. This would be the origin + * of the parent viewer. + * @return {?string} + */ + maybeGetMessagingOrigin() {} + + /** + * Returns an unconfirmed "referrer" URL that can be optionally customized by + * the viewer. Consider using `getReferrerUrl()` instead, which returns the + * promise that will yield the confirmed "referrer" URL. + * @return {string} + */ + getUnconfirmedReferrerUrl() {} + + /** + * Returns the promise that will yield the confirmed "referrer" URL. This + * URL can be optionally customized by the viewer, but viewer is required + * to be a trusted viewer. + * @return {!Promise} + */ + getReferrerUrl() {} + + /** + * Whether the viewer has been whitelisted for more sensitive operations + * such as customizing referrer. + * @return {!Promise} + */ + isTrustedViewer() {} + + /** + * Returns the promise that resolves to URL representing the origin of the + * viewer. If the document is not embedded or if a viewer origin can't be + * found, empty string is returned. + * @return {!Promise} + */ + getViewerOrigin() {} + + /** + * Adds a "visibilitychange" event listener for viewer events. The + * callback can check {@link isVisible} and {@link getPrefetchCount} + * methods for more info. + * @param {function()} handler + * @return {!UnlistenDef} + * TODO(#22733): deprecate/remove when ampdoc-fie is launched. + */ + onVisibilityChanged(handler) {} + + /** + * Adds a eventType listener for viewer events. + * @param {string} eventType + * @param {function(!JsonObject)} handler + * @return {!UnlistenDef} + */ + onMessage(eventType, handler) {} + + /** + * Adds a eventType listener for viewer events. + * @param {string} eventType + * @param {!RequestResponderDef} responder + * @return {!UnlistenDef} + */ + onMessageRespond(eventType, responder) {} + + /** + * Requests AMP document to receive a message from Viewer. + * @param {string} eventType + * @param {!JsonObject} data + * @param {boolean} unusedAwaitResponse + * @return {(!Promise<*>|undefined)} + * @export + */ + receiveMessage(eventType, data, unusedAwaitResponse) {} + + /** + * Provides a message delivery mechanism by which AMP document can send + * messages to the viewer. + * @param {function(string, (?JsonObject|string|undefined), boolean): + * (!Promise<*>|undefined)} deliverer + * @param {string} origin + * @export + */ + setMessageDeliverer(deliverer, origin) {} + + /** + * Sends the message to the viewer without waiting for any response. + * If cancelUnsent is true, the previous message of the same message type will + * be canceled. + * + * This is a restricted API. + * + * @param {string} eventType + * @param {?JsonObject|string|undefined} data + * @param {boolean=} cancelUnsent + */ + sendMessage(eventType, data, cancelUnsent = false) {} + + /** + * Sends the message to the viewer and wait for response. + * If cancelUnsent is true, the previous message of the same message type will + * be canceled. + * + * This is a restricted API. + * + * @param {string} eventType + * @param {?JsonObject|string|undefined} data + * @param {boolean=} cancelUnsent + * @return {!Promise<(?JsonObject|string|undefined)>} the response promise + */ + sendMessageAwaitResponse(eventType, data, cancelUnsent = false) {} + + /** + * Broadcasts a message to all other AMP documents under the same viewer. It + * will attempt to deliver messages when the messaging channel has been + * established, but it will not fail if the channel is timed out. + * + * @param {!JsonObject} message + * @return {!Promise} a Promise of success or not + */ + broadcast(message) {} + + /** + * Registers receiver for the broadcast events. + * @param {function(!JsonObject)} handler + * @return {!UnlistenDef} + */ + onBroadcast(handler) {} + + /** + * Resolves when there is a messaging channel established with the viewer. + * Will be null if no messaging is needed like in an non-embedded document. + * Deprecated: do not use. sendMessage and sendMessageAwaitResponse already + * wait for messaging channel ready. + * @return {?Promise} + */ + whenMessagingReady() {} + + /** + * Replace the document url with the viewer provided new replaceUrl. + * @param {?string} newUrl + */ + replaceUrl(newUrl) {} +} +/* eslint-enable no-unused-vars */ diff --git a/src/service/viewport/viewport-impl.js b/src/service/viewport/viewport-impl.js index 8ace31ef16f8..cb52448da915 100644 --- a/src/service/viewport/viewport-impl.js +++ b/src/service/viewport/viewport-impl.js @@ -61,7 +61,7 @@ export class ViewportImpl { /** * @param {!../ampdoc-impl.AmpDoc} ampdoc * @param {!ViewportBindingDef} binding - * @param {!../viewer-impl.Viewer} viewer + * @param {!../viewer-interface.ViewerInterface} viewer */ constructor(ampdoc, binding, viewer) { const {win} = ampdoc; @@ -78,7 +78,7 @@ export class ViewportImpl { /** @const {!ViewportBindingDef} */ this.binding_ = binding; - /** @const {!../viewer-impl.Viewer} */ + /** @const {!../viewer-interface.ViewerInterface} */ this.viewer_ = viewer; /** @@ -1167,7 +1167,7 @@ const ViewportType = { /** * @param {!Window} win - * @param {!../viewer-impl.Viewer} viewer + * @param {!../viewer-interface.ViewerInterface} viewer * @return {string} */ function getViewportType(win, viewer) { diff --git a/src/service/vsync-impl.js b/src/service/vsync-impl.js index 51921c7a6386..76a518a4cea6 100644 --- a/src/service/vsync-impl.js +++ b/src/service/vsync-impl.js @@ -132,7 +132,7 @@ export class Vsync { FRAME_TIME * 2.5 ); - /** @private {?./viewer-impl.Viewer} */ + /** @private {?./viewer-interface.ViewerInterface} */ this.singleDocViewer_ = null; // When the document changes visibility, vsync has to reschedule the queue diff --git a/src/services.js b/src/services.js index e4c99de2a1da..1ab273fef663 100644 --- a/src/services.js +++ b/src/services.js @@ -793,10 +793,10 @@ export class Services { /** * @param {!Element|!./service/ampdoc-impl.AmpDoc} elementOrAmpDoc - * @return {!./service/viewer-impl.Viewer} + * @return {!./service/viewer-interface.ViewerInterface} */ static viewerForDoc(elementOrAmpDoc) { - return /** @type {!./service/viewer-impl.Viewer} */ (getServiceForDoc( + return /** @type {!./service/viewer-interface.ViewerInterface} */ (getServiceForDoc( elementOrAmpDoc, 'viewer' )); @@ -807,10 +807,10 @@ export class Services { * for services that need reference to the viewer before it has been * initialized. Most of the code, however, just should use `viewerForDoc`. * @param {!Element|!./service/ampdoc-impl.AmpDoc} elementOrAmpDoc - * @return {!Promise} + * @return {!Promise} */ static viewerPromiseForDoc(elementOrAmpDoc) { - return /** @type {!Promise} */ (getServicePromiseForDoc( + return /** @type {!Promise} */ (getServicePromiseForDoc( elementOrAmpDoc, 'viewer' )); diff --git a/src/ssr-template-helper.js b/src/ssr-template-helper.js index 88bb9d3bfd0a..80c4100b2a15 100644 --- a/src/ssr-template-helper.js +++ b/src/ssr-template-helper.js @@ -33,7 +33,7 @@ export let SsrTemplateDef; export class SsrTemplateHelper { /** * @param {string} sourceComponent - * @param {!./service/viewer-impl.Viewer} viewer + * @param {!./service/viewer-interface.ViewerInterface} viewer * @param {!./service/template-impl.Templates} templates */ constructor(sourceComponent, viewer, templates) { @@ -54,7 +54,7 @@ export class SsrTemplateHelper { * @return {boolean} */ isSupported() { - const {ampdoc} = this.viewer_; + const ampdoc = this.viewer_.getAmpDoc(); if (ampdoc.isSingleDoc()) { const htmlElement = ampdoc.getRootNode().documentElement; if (htmlElement.hasAttribute('allow-viewer-render-template')) { diff --git a/test/unit/test-viewer.js b/test/unit/test-viewer.js index 3c836c0aa24f..d7cf0e2a3e97 100644 --- a/test/unit/test-viewer.js +++ b/test/unit/test-viewer.js @@ -15,7 +15,7 @@ */ import {Services} from '../../src/services'; -import {Viewer} from '../../src/service/viewer-impl'; +import {ViewerImpl} from '../../src/service/viewer-impl'; import {dev} from '../../src/log'; import {installDocService} from '../../src/service/ampdoc-impl'; import {installDocumentInfoServiceForDoc} from '../../src/service/document-info-impl'; @@ -126,7 +126,7 @@ describes.sandboxed('Viewer', {}, () => { errorStub = sandbox.stub(dev(), 'error'); expectedErrorStub = sandbox.stub(dev(), 'expectedError'); windowMock = sandbox.mock(windowApi); - viewer = new Viewer(ampdoc); + viewer = new ViewerImpl(ampdoc); }); afterEach(() => { @@ -136,14 +136,14 @@ describes.sandboxed('Viewer', {}, () => { it('should configure correctly based on ampdoc', () => { params['paddingTop'] = '17'; params['other'] = 'something'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getParam('paddingTop')).to.equal('17'); expect(viewer.getParam('other')).to.equal('something'); }); it('should expose viewer capabilities', () => { params['cap'] = 'foo,bar'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.hasCapability('foo')).to.be.true; expect(viewer.hasCapability('bar')).to.be.true; expect(viewer.hasCapability('other')).to.be.false; @@ -152,7 +152,7 @@ describes.sandboxed('Viewer', {}, () => { it('should not clear fragment in non-embedded mode', () => { windowApi.parent = windowApi; setUrl('http://www.example.com#test=1'); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(windowApi.history.replaceState).to.have.not.been.called; expect(viewer.getParam('test')).to.equal('1'); expect(viewer.hasCapability('foo')).to.be.false; @@ -161,7 +161,7 @@ describes.sandboxed('Viewer', {}, () => { it('should not clear fragment in embedded mode', () => { windowApi.parent = {}; setUrl('http://www.example.com#origin=g.com&test=1'); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(windowApi.history.replaceState).to.not.be.called; expect(viewer.getParam('test')).to.equal('1'); }); @@ -172,7 +172,7 @@ describes.sandboxed('Viewer', {}, () => { // windowApi.location.href = 'http://www.example.com/'; // windowApi.location.search = '?amp_gsa=1&_js_v=a0'; // windowApi.location.hash = ''; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.isCctEmbedded()).to.be.true; yield viewer.whenFirstVisible(); expect(windowApi.history.replaceState).to.be.calledWith( @@ -185,7 +185,7 @@ describes.sandboxed('Viewer', {}, () => { it('should merge fragments within custom tab', function*() { windowApi.parent = windowApi; setUrl('http://www.example.com/?amp_gsa=1&_js_v=a0#test=1'); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getParam('test')).to.equal('1'); expect(viewer.isCctEmbedded()).to.be.true; yield viewer.whenFirstVisible(); @@ -203,7 +203,7 @@ describes.sandboxed('Viewer', {}, () => { '?amp_gsa=1&_js_v=a0' + '#test=1&share=old' ); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getParam('test')).to.equal('1'); expect(viewer.isCctEmbedded()).to.be.true; yield viewer.whenFirstVisible(); @@ -220,7 +220,7 @@ describes.sandboxed('Viewer', {}, () => { 'http://www.example.com/?amp_gsa=1&_js_v=a0' + '#test=1&share=a&share=b&share=c' ); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getParam('test')).to.equal('1'); expect(viewer.isCctEmbedded()).to.be.true; yield viewer.whenFirstVisible(); @@ -243,7 +243,7 @@ describes.sandboxed('Viewer', {}, () => { // windowApi.location.search = '?amp_gsa=1&_js_v=a0'; // params['test'] = '1'; // params['ampshare'] = 'old'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getParam('test')).to.equal('1'); expect(viewer.isCctEmbedded()).to.be.true; yield viewer.whenFirstVisible(); @@ -261,7 +261,7 @@ describes.sandboxed('Viewer', {}, () => { '?amp_gsa=1&_js_v=a0' + '#note=ok&share=old&test=1' ); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getParam('test')).to.equal('1'); expect(viewer.getParam('note')).to.equal('ok'); expect(viewer.isCctEmbedded()).to.be.true; @@ -276,7 +276,7 @@ describes.sandboxed('Viewer', {}, () => { it('should clear fragment when click param is present', () => { windowApi.parent = windowApi; setUrl('http://www.example.com/#click=abc'); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(windowApi.history.replaceState).to.be.calledOnce; const replace = windowApi.history.replaceState.lastCall; expect(replace.args).to.jsonEqual([{}, '', 'http://www.example.com/']); @@ -286,7 +286,7 @@ describes.sandboxed('Viewer', {}, () => { it('should restore fragment within custom tab with click param', function*() { windowApi.parent = windowApi; setUrl('http://www.example.com/?amp_gsa=1&_js_v=a0#click=abc'); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(windowApi.history.replaceState).to.be.calledWith( {}, '', @@ -310,7 +310,7 @@ describes.sandboxed('Viewer', {}, () => { }); it('should return promise that resolve on visible', function*() { - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.isVisible()).to.be.true; let promise = viewer.whenNextVisible(); yield promise; @@ -327,7 +327,7 @@ describes.sandboxed('Viewer', {}, () => { it('should initialize firstVisibleTime when doc becomes visible', () => { params['prerenderSize'] = '3'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.isVisible()).to.be.true; expect(viewer.getFirstVisibleTime()).to.equal(0); expect(viewer.getLastVisibleTime()).to.equal(0); @@ -362,7 +362,7 @@ describes.sandboxed('Viewer', {}, () => { it('should configure prerenderSize', () => { params['prerenderSize'] = '3'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getPrerenderSize()).to.equal(3); }); @@ -381,7 +381,7 @@ describes.sandboxed('Viewer', {}, () => { it('should replace URL for the same non-proxy origin', () => { const fragment = '#replaceUrl=http://www.example.com/two%3Fa%3D1&b=1'; setUrl('http://www.example.com/one' + fragment); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.replaceUrl(viewer.getParam('replaceUrl')); expect(windowApi.history.replaceState).to.be.calledOnce; expect(windowApi.history.replaceState).to.be.calledWith( @@ -400,7 +400,7 @@ describes.sandboxed('Viewer', {}, () => { it('should ignore replacement fragment', () => { const fragment = '#replaceUrl=http://www.example.com/two%23b=2&b=1'; setUrl('http://www.example.com/one' + fragment); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.replaceUrl(viewer.getParam('replaceUrl')); expect(windowApi.history.replaceState).to.be.calledOnce; expect(windowApi.history.replaceState).to.be.calledWith( @@ -416,7 +416,7 @@ describes.sandboxed('Viewer', {}, () => { it('should replace relative URL for the same non-proxy origin', () => { const fragment = '#replaceUrl=/two&b=1'; setUrl(removeFragment(window.location.href) + fragment); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.replaceUrl(viewer.getParam('replaceUrl')); expect(windowApi.history.replaceState).to.be.calledOnce; expect(windowApi.history.replaceState).to.be.calledWith( @@ -432,7 +432,7 @@ describes.sandboxed('Viewer', {}, () => { it('should fail to replace URL for a wrong non-proxy origin', () => { const fragment = '#replaceUrl=http://other.example.com/two&b=1'; setUrl('http://www.example.com/one' + fragment); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.replaceUrl(viewer.getParam('replaceUrl')); expect(windowApi.history.replaceState).to.not.be.called; expect(windowApi.location.originalHref).to.be.undefined; @@ -445,7 +445,7 @@ describes.sandboxed('Viewer', {}, () => { sandbox.stub(windowApi.history, 'replaceState').callsFake(() => { throw new Error('intentional'); }); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(() => { viewer.replaceUrl(viewer.getParam('replaceUrl')); }).to.not.throw(); @@ -456,7 +456,7 @@ describes.sandboxed('Viewer', {}, () => { const fragment = '#replaceUrl=https://cdn.ampproject.org/c/www.example.com/two&b=1'; setUrl('https://cdn.ampproject.org/c/www.example.com/one' + fragment); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.replaceUrl(viewer.getParam('replaceUrl')); expect(windowApi.history.replaceState).to.be.calledOnce; expect(windowApi.history.replaceState).to.be.calledWith( @@ -473,7 +473,7 @@ describes.sandboxed('Viewer', {}, () => { const fragment = '#replaceUrl=https://cdn.ampproject.org/c/other.example.com/two&b=1'; setUrl('https://cdn.ampproject.org/c/www.example.com/one' + fragment); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.replaceUrl(viewer.getParam('replaceUrl')); expect(windowApi.history.replaceState).to.not.be.called; expect(windowApi.location.originalHref).to.be.undefined; @@ -483,7 +483,7 @@ describes.sandboxed('Viewer', {}, () => { const fragment = '#replaceUrl=http://www.example.com/two&b=1'; setUrl('http://www.example.com/one' + fragment); sandbox.stub(ampdoc, 'isSingleDoc').callsFake(() => false); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.replaceUrl(viewer.getParam('replaceUrl')); expect(windowApi.history.replaceState).to.not.be.called; }); @@ -698,7 +698,7 @@ describes.sandboxed('Viewer', {}, () => { describe('Messaging embedded', () => { beforeEach(() => { windowApi.parent = {}; - viewer = new Viewer(ampdoc); + viewer = new ViewerImpl(ampdoc); }); it('should receive broadcast event', () => { @@ -931,43 +931,43 @@ describes.sandboxed('Viewer', {}, () => { it('should NOT be embedded when not iframed', () => { windowApi.parent = windowApi; params = {'origin': 'g.com'}; - expect(new Viewer(ampdoc).isEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.false; }); it('should be embedded when iframed w/ "origin" in URL hash', () => { windowApi.parent = {}; params = {'origin': 'g.com'}; - expect(new Viewer(ampdoc).isEmbedded()).to.be.true; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.true; }); it('should be embedded when iframed w/ "visibilityState"', () => { windowApi.parent = {}; params = {'visibilityState': 'hidden'}; - expect(new Viewer(ampdoc).isEmbedded()).to.be.true; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.true; }); it('should NOT be embedded when iframed w/o "origin" param', () => { windowApi.parent = {}; params = {}; - expect(new Viewer(ampdoc).isEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.false; }); it('should be embedded with "webview=1" param', () => { windowApi.parent = windowApi; params = {'webview': '1'}; - expect(new Viewer(ampdoc).isEmbedded()).to.be.true; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.true; }); it('should be embedded with query param', () => { windowApi.parent = {}; windowApi.location.search = '?amp_js_v=1'; - expect(new Viewer(ampdoc).isEmbedded()).to.be.true; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.true; }); it('should be embedded when isCctEmbedded', () => { windowApi.parent = {}; windowApi.location.search = '?amp_gsa=1&_js_v=a0'; - expect(new Viewer(ampdoc).isEmbedded()).to.be.true; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.true; }); }); @@ -975,25 +975,25 @@ describes.sandboxed('Viewer', {}, () => { it('should be webview w/ "webview=1"', () => { windowApi.parent = windowApi; params = {'webview': '1'}; - expect(new Viewer(ampdoc).isWebviewEmbedded()).to.be.true; + expect(new ViewerImpl(ampdoc).isWebviewEmbedded()).to.be.true; }); it('should NOT be webview w/o "webview=1"', () => { windowApi.parent = windowApi; params = {'foo': '1'}; - expect(new Viewer(ampdoc).isWebviewEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isWebviewEmbedded()).to.be.false; }); it('should NOT be webview w/ "webview=0"', () => { windowApi.parent = windowApi; params = {'webview': '0'}; - expect(new Viewer(ampdoc).isWebviewEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isWebviewEmbedded()).to.be.false; }); it('should NOT be webview if iframed regardless of "webview=1"', () => { windowApi.parent = {}; params = {'webview': '1'}; - expect(new Viewer(ampdoc).isEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isEmbedded()).to.be.false; }); }); @@ -1001,31 +1001,31 @@ describes.sandboxed('Viewer', {}, () => { it('should be CCT embedded with "amp_gsa=1" and "amp_js_v=a\\d*"', () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_gsa=1&_js_v=a0'; - expect(new Viewer(ampdoc).isCctEmbedded()).to.be.true; + expect(new ViewerImpl(ampdoc).isCctEmbedded()).to.be.true; }); it('should NOT be CCT embedded w/o "amp_gsa=1"', () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_js_v=a0'; - expect(new Viewer(ampdoc).isCctEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isCctEmbedded()).to.be.false; }); it('should NOT be CCT embedded w/ "amp_gsa=0"', () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_gsa=0&_js_v=a0'; - expect(new Viewer(ampdoc).isCctEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isCctEmbedded()).to.be.false; }); it('should NOT be CCT embedded w/ "amp_js_v" not starting with "a"', () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_gsa=1&_js_v=0'; - expect(new Viewer(ampdoc).isCctEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isCctEmbedded()).to.be.false; }); it('should NOT be CCT embedded if iframed regardless of "amp_gsa=1"', () => { windowApi.parent = {}; windowApi.location.search = '?amp_gsa=0&_js_v=a0'; - expect(new Viewer(ampdoc).isCctEmbedded()).to.be.false; + expect(new ViewerImpl(ampdoc).isCctEmbedded()).to.be.false; }); }); @@ -1033,7 +1033,7 @@ describes.sandboxed('Viewer', {}, () => { it('should consider non-trusted when not iframed', () => { windowApi.parent = windowApi; windowApi.location.ancestorOrigins = ['https://google.com']; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.false; }); }); @@ -1041,7 +1041,7 @@ describes.sandboxed('Viewer', {}, () => { it('should consider trusted by ancestor', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = ['https://google.com']; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.true; }); }); @@ -1049,7 +1049,7 @@ describes.sandboxed('Viewer', {}, () => { it('should consider trusted by ancestor', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = ['https://gmail.dev']; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.true; }); }); @@ -1057,7 +1057,7 @@ describes.sandboxed('Viewer', {}, () => { it('should consider non-trusted without ancestor', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = []; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.false; }); }); @@ -1065,7 +1065,7 @@ describes.sandboxed('Viewer', {}, () => { it('should consider non-trusted with wrong ancestor', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = ['https://untrusted.com']; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.false; }); }); @@ -1073,7 +1073,7 @@ describes.sandboxed('Viewer', {}, () => { it('should decide trusted on connection with origin', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = null; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://google.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.true; @@ -1083,7 +1083,7 @@ describes.sandboxed('Viewer', {}, () => { it('should NOT allow channel without origin', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = null; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(() => { viewer.setMessageDeliverer(() => {}); }).to.throw(/message channel must have an origin/); @@ -1092,7 +1092,7 @@ describes.sandboxed('Viewer', {}, () => { it('should allow channel without origin thats an empty string', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = null; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(() => { viewer.setMessageDeliverer(() => {}, ''); }).to.not.throw(/message channel must have an origin/); @@ -1101,7 +1101,7 @@ describes.sandboxed('Viewer', {}, () => { it('should decide non-trusted on connection with wrong origin', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = null; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.false; @@ -1111,7 +1111,7 @@ describes.sandboxed('Viewer', {}, () => { it('should give precedence to ancestor', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.true; @@ -1123,7 +1123,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; params = {'webview': '1'}; windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://google.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.true; @@ -1134,7 +1134,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; params = {'webview': '1'}; windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(() => { viewer.setMessageDeliverer(() => {}); }).to.throw(/message channel must have an origin/); @@ -1144,7 +1144,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; params = {'webview': '1'}; windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.false; @@ -1155,7 +1155,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; params = {'webview': '1'}; windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.false; @@ -1168,7 +1168,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_gsa=1&_js_v=a0'; windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://google.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.true; @@ -1179,7 +1179,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_gsa=1&_js_v=a0'; windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(() => { viewer.setMessageDeliverer(() => {}); }).to.throw(/message channel must have an origin/); @@ -1189,7 +1189,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_gsa=1&_js_v=a0'; windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.false; @@ -1200,7 +1200,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; windowApi.location.search = '?amp_gsa=1&_js_v=a0'; windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.false; @@ -1213,7 +1213,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; params = {'origin': 'g.com', 'webview': '1'}; windowApi.location.ancestorOrigins = ['https://google.com']; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.true; }); }); @@ -1222,7 +1222,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; params = {'origin': 'g.com', 'webview': '1'}; windowApi.location.ancestorOrigins = []; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.false; }); }); @@ -1231,7 +1231,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; params = {'origin': 'g.com', 'webview': '1'}; windowApi.location.ancestorOrigins = ['https://untrusted.com']; - return new Viewer(ampdoc).isTrustedViewer().then(res => { + return new ViewerImpl(ampdoc).isTrustedViewer().then(res => { expect(res).to.be.false; }); }); @@ -1240,7 +1240,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; params = {'origin': 'g.com', 'webview': '1'}; windowApi.location.ancestorOrigins = null; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://google.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.true; @@ -1251,7 +1251,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; params = {'origin': 'g.com', 'webview': '1'}; windowApi.location.ancestorOrigins = null; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(() => { viewer.setMessageDeliverer(() => {}); }).to.throw(/message channel must have an origin/); @@ -1261,7 +1261,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; params = {'origin': 'g.com', 'webview': '1'}; windowApi.location.ancestorOrigins = null; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.false; @@ -1272,7 +1272,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; params = {'origin': 'g.com', 'webview': '1'}; windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.isTrustedViewer().then(res => { expect(res).to.be.true; @@ -1288,7 +1288,7 @@ describes.sandboxed('Viewer', {}, () => { */ function testHasRoughlySameOrigin(first, second) { it('should find ' + first + ' and ' + second + ' to match', () => { - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.hasRoughlySameOrigin_(first, second)).to.be.true; }); } @@ -1301,7 +1301,7 @@ describes.sandboxed('Viewer', {}, () => { */ function testHasRoughlyDifferentOrigin(first, second) { it('should NOT find ' + first + ' and ' + second + ' to match', () => { - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.hasRoughlySameOrigin_(first, second)).to.be.false; }); } @@ -1402,7 +1402,7 @@ describes.sandboxed('Viewer', {}, () => { */ function test(origin, toBeTrusted, opt_inWebView) { it('testing ' + origin, () => { - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); viewer.isWebviewEmbedded_ = !!opt_inWebView; expect(viewer.isTrustedViewerOrigin_(origin)).to.equal(toBeTrusted); }); @@ -1448,7 +1448,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; setUrl('#'); windowApi.document.referrer = 'https://acme.org/docref'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getUnconfirmedReferrerUrl()).to.equal( 'https://acme.org/docref' ); @@ -1462,7 +1462,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = windowApi; setUrl('#referrer=' + encodeURIComponent('https://acme.org/viewer')); windowApi.document.referrer = 'https://acme.org/docref'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getUnconfirmedReferrerUrl()).to.equal( 'https://acme.org/docref' ); @@ -1479,7 +1479,7 @@ describes.sandboxed('Viewer', {}, () => { encodeURIComponent('https://acme.org/viewer'); windowApi.document.referrer = 'https://acme.org/docref'; windowApi.location.ancestorOrigins = ['https://untrusted.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getUnconfirmedReferrerUrl()).to.equal( 'https://acme.org/docref' ); @@ -1496,7 +1496,7 @@ describes.sandboxed('Viewer', {}, () => { encodeURIComponent('https://acme.org/viewer'); windowApi.document.referrer = 'https://acme.org/docref'; windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getUnconfirmedReferrerUrl()).to.equal( 'https://acme.org/docref' ); @@ -1513,7 +1513,7 @@ describes.sandboxed('Viewer', {}, () => { encodeURIComponent('https://acme.org/viewer') ); windowApi.document.referrer = 'https://acme.org/docref'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); // Unconfirmed referrer is overriden, but not confirmed yet. expect(viewer.getUnconfirmedReferrerUrl()).to.equal( 'https://acme.org/viewer' @@ -1544,7 +1544,7 @@ describes.sandboxed('Viewer', {}, () => { encodeURIComponent('https://acme.org/viewer') ); windowApi.document.referrer = 'https://acme.org/docref'; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); // Unconfirmed referrer is overriden and will be confirmed next. expect(viewer.getUnconfirmedReferrerUrl()).to.equal( 'https://acme.org/viewer' @@ -1568,7 +1568,7 @@ describes.sandboxed('Viewer', {}, () => { ); windowApi.document.referrer = 'https://acme.org/docref'; windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getUnconfirmedReferrerUrl()).to.equal( 'https://acme.org/viewer' ); @@ -1583,7 +1583,7 @@ describes.sandboxed('Viewer', {}, () => { setUrl('#origin=g.com&referrer='); windowApi.document.referrer = 'https://acme.org/docref'; windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getUnconfirmedReferrerUrl()).to.equal(''); return viewer.getReferrerUrl().then(referrerUrl => { expect(referrerUrl).to.equal(''); @@ -1595,14 +1595,14 @@ describes.sandboxed('Viewer', {}, () => { describe('viewerUrl', () => { it('should initially always return current location', () => { setUrl('https://acme.org/doc1#hash'); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); }); it('should always return current location for top-level window', () => { windowApi.parent = windowApi; setUrl('https://acme.org/doc1#hash'); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); return viewer.getViewerUrl().then(viewerUrl => { expect(viewerUrl).to.equal('https://acme.org/doc1'); @@ -1617,7 +1617,7 @@ describes.sandboxed('Viewer', {}, () => { 'https://acme.org/doc1#origin=g.com&viewerUrl=' + encodeURIComponent('https://acme.org/viewer') ); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); return viewer.getViewerUrl().then(viewerUrl => { expect(viewerUrl).to.equal('https://acme.org/doc1'); @@ -1633,7 +1633,7 @@ describes.sandboxed('Viewer', {}, () => { encodeURIComponent('https://acme.org/viewer') ); windowApi.location.ancestorOrigins = ['https://untrusted.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); return viewer.getViewerUrl().then(viewerUrl => { expect(viewerUrl).to.equal('https://acme.org/doc1'); @@ -1657,7 +1657,7 @@ describes.sandboxed('Viewer', {}, () => { encodeURIComponent('https://acme.org/viewer') ); windowApi.location.ancestorOrigins = []; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); return viewer.getViewerUrl().then(viewerUrl => { expect(viewerUrl).to.equal('https://acme.org/doc1'); @@ -1680,7 +1680,7 @@ describes.sandboxed('Viewer', {}, () => { 'https://acme.org/doc1#origin=g.com&viewerUrl=' + encodeURIComponent('https://acme.org/viewer') ); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); viewer.setMessageDeliverer(() => {}, 'https://untrusted.com'); return viewer.getViewerUrl().then(viewerUrl => { @@ -1704,7 +1704,7 @@ describes.sandboxed('Viewer', {}, () => { 'https://acme.org/doc1#origin=g.com&viewerUrl=' + encodeURIComponent('https://acme.org/viewer') ); - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); viewer.setMessageDeliverer(() => {}, 'https://google.com'); return viewer.getViewerUrl().then(viewerUrl => { @@ -1723,7 +1723,7 @@ describes.sandboxed('Viewer', {}, () => { encodeURIComponent('https://acme.org/viewer') ); windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); return viewer.getViewerUrl().then(viewerUrl => { expect(viewerUrl).to.equal('https://acme.org/viewer'); @@ -1738,7 +1738,7 @@ describes.sandboxed('Viewer', {}, () => { windowApi.parent = {}; setUrl('https://acme.org/doc1#origin=g.com&viewerUrl='); windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); expect(viewer.getResolvedViewerUrl()).to.equal('https://acme.org/doc1'); return viewer.getViewerUrl().then(viewerUrl => { expect(viewerUrl).to.equal('https://acme.org/doc1'); @@ -1750,7 +1750,7 @@ describes.sandboxed('Viewer', {}, () => { describe('viewerOrigin', () => { it('should return empty string if origin is not known', () => { - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); return viewer.getViewerOrigin().then(viewerOrigin => { expect(viewerOrigin).to.equal(''); }); @@ -1759,7 +1759,7 @@ describes.sandboxed('Viewer', {}, () => { it('should return ancestor origin if known', () => { windowApi.parent = {}; windowApi.location.ancestorOrigins = ['https://google.com']; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); return viewer.getViewerOrigin().then(viewerOrigin => { expect(viewerOrigin).to.equal('https://google.com'); }); @@ -1767,7 +1767,7 @@ describes.sandboxed('Viewer', {}, () => { it('should return viewer origin if set via handshake', () => { windowApi.parent = {}; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); const result = viewer.getViewerOrigin().then(viewerOrigin => { expect(viewerOrigin).to.equal('https://foobar.com'); }); @@ -1777,7 +1777,7 @@ describes.sandboxed('Viewer', {}, () => { it('should return empty string if handshake does not happen', () => { windowApi.parent = {}; - const viewer = new Viewer(ampdoc); + const viewer = new ViewerImpl(ampdoc); const result = viewer.getViewerOrigin().then(viewerOrigin => { expect(viewerOrigin).to.equal(''); });