diff --git a/third_party/subscriptions-project/config.js b/third_party/subscriptions-project/config.js index 59f4afec2723..45fba72a0478 100644 --- a/third_party/subscriptions-project/config.js +++ b/third_party/subscriptions-project/config.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** Version: 0.1.22.150 */ +/** Version: 0.1.22.151 */ /** * Copyright 2018 The Subscribe with Google Authors. All Rights Reserved. * diff --git a/third_party/subscriptions-project/swg-gaa.js b/third_party/subscriptions-project/swg-gaa.js index 51790f3ddefd..5f0d742599f0 100644 --- a/third_party/subscriptions-project/swg-gaa.js +++ b/third_party/subscriptions-project/swg-gaa.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** Version: 0.1.22.150 */ +/** Version: 0.1.22.151 */ /** * Copyright 2018 The Subscribe with Google Authors. All Rights Reserved. * @@ -651,6 +651,9 @@ const POST_MESSAGE_COMMAND_INTRODUCTION = 'introduction'; /** User command for post messages. */ const POST_MESSAGE_COMMAND_USER = 'user'; +/** Error command for post messages. */ +const POST_MESSAGE_COMMAND_ERROR = 'error'; + /** ID for the Google Sign-In iframe element. */ const GOOGLE_SIGN_IN_IFRAME_ID = 'swg-google-sign-in-iframe'; @@ -942,10 +945,18 @@ class GaaMeteringRegwall { GaaMeteringRegwall.render_({iframeUrl}); GaaMeteringRegwall.sendIntroMessageToGsiIframe_({iframeUrl}); - return GaaMeteringRegwall.getGaaUser_().then((gaaUser) => { - GaaMeteringRegwall.remove_(); - return gaaUser; - }); + return GaaMeteringRegwall.getGaaUser_() + .then((gaaUser) => { + GaaMeteringRegwall.remove_(); + return gaaUser; + }) + .catch((err) => { + // Close the Regwall, since the flow failed. + GaaMeteringRegwall.remove_(); + + // Rethrow error. + throw err; + }); } /** @@ -1080,13 +1091,18 @@ class GaaMeteringRegwall { */ static getGaaUser_() { // Listen for GAA user. - return new Promise((resolve) => { + return new Promise((resolve, reject) => { self.addEventListener('message', (e) => { - if ( - e.data.stamp === POST_MESSAGE_STAMP && - e.data.command === POST_MESSAGE_COMMAND_USER - ) { - resolve(e.data.gaaUser); + if (e.data.stamp === POST_MESSAGE_STAMP) { + if (e.data.command === POST_MESSAGE_COMMAND_USER) { + // Pass along GAA user. + resolve(e.data.gaaUser); + } + + if (e.data.command === POST_MESSAGE_COMMAND_ERROR) { + // Reject promise due to Google Sign-In error. + reject('Google Sign-In failed to initialize'); + } } }); }); @@ -1145,7 +1161,7 @@ class GaaGoogleSignInButton { const styleEl = self.document.createElement('style'); styleEl./*OK*/ innerText = GOOGLE_SIGN_IN_IFRAME_STYLES.replace( '$SHOWCASE_REGWALL_GOOGLE_SIGN_IN_BUTTON$', - I18N_STRINGS['SHOWCASE_REGWALL_GOOGLE_SIGN_IN_BUTTON'][languageCode] + msg(I18N_STRINGS['SHOWCASE_REGWALL_GOOGLE_SIGN_IN_BUTTON'], languageCode) ); self.document.head.appendChild(styleEl); @@ -1210,6 +1226,15 @@ class GaaGoogleSignInButton { gaaUser, }); }); + }) + .catch(() => { + // Report error to parent frame. + sendMessageToParentFnPromise.then((sendMessageToParent) => { + sendMessageToParent({ + stamp: POST_MESSAGE_STAMP, + command: POST_MESSAGE_COMMAND_ERROR, + }); + }); }); } } diff --git a/third_party/subscriptions-project/swg.js b/third_party/subscriptions-project/swg.js index 7280ddae6b5f..f2b35fc9e896 100644 --- a/third_party/subscriptions-project/swg.js +++ b/third_party/subscriptions-project/swg.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/** Version: 0.1.22.150 */ +/** Version: 0.1.22.151 */ /** * Copyright 2018 The Subscribe with Google Authors. All Rights Reserved. * @@ -1448,7 +1448,7 @@ class SmartBoxMessage { /** * @implements {Message} */ -class SubscribeResponse { +class SubscribeResponse$1 { /** * @param {!Array<*>=} data * @param {boolean=} includesLabel @@ -1690,7 +1690,7 @@ const PROTO_MAP = { 'LinkingInfoResponse': LinkingInfoResponse, 'SkuSelectedResponse': SkuSelectedResponse, 'SmartBoxMessage': SmartBoxMessage, - 'SubscribeResponse': SubscribeResponse, + 'SubscribeResponse': SubscribeResponse$1, 'Timestamp': Timestamp, 'ToastCloseRequest': ToastCloseRequest, 'ViewSubscriptionsResponse': ViewSubscriptionsResponse, @@ -2234,7 +2234,7 @@ function base64UrlDecodeToBytes(str) { * limitations under the License. */ -const CHARS = '0123456789ABCDEF'; +const CHARS$1 = '0123456789ABCDEF'; /** * Polyfill for String.prototype.startsWith. @@ -2255,7 +2255,7 @@ function startsWith(string, prefix) { * @param {!number} v */ function getChar19(v) { - return CHARS[(v & 0x3) | 0x8]; + return CHARS$1[(v & 0x3) | 0x8]; } /** @@ -2291,7 +2291,7 @@ function getUuid() { uuid += getChar19(rands[rIndex++]); break; default: - uuid += CHARS[rands[rIndex++]]; + uuid += CHARS$1[rands[rIndex++]]; break; } } @@ -2559,7 +2559,7 @@ function getVendorJsPropertyName(style, camelCase, bypassCache) { * @param {!Element} element * @param {!Object} styles */ -function setImportantStyles(element, styles) { +function setImportantStyles$1(element, styles) { for (const k in styles) { element.style.setProperty( getVendorJsPropertyName(styles, k), @@ -2621,7 +2621,7 @@ function resetStyles(element, properties) { * @param {!Element} element */ function resetAllStyles(element) { - setImportantStyles(element, defaultStyles); + setImportantStyles$1(element, defaultStyles); } /** @@ -2959,7 +2959,7 @@ let aResolver; * @param {string} urlString * @return {!HTMLAnchorElement} */ -function parseUrl(urlString) { +function parseUrl$1(urlString) { if (!aResolver) { aResolver = /** @type {!HTMLAnchorElement} */ (document.createElement('a')); } @@ -2994,7 +2994,7 @@ function getOrigin(loc) { * @return {string} */ function getOriginFromUrl(urlString) { - return getOrigin(parseUrl(urlString)); + return getOrigin(parseUrl$1(urlString)); } @@ -3016,7 +3016,7 @@ function removeFragment(urlString) { * @param {string} query The URL query string. * @return {!Object} */ -function parseQueryString(query) { +function parseQueryString$1(query) { if (!query) { return {}; } @@ -3041,7 +3041,7 @@ function parseQueryString(query) { * @return {?string} */ function getQueryParam(queryString, param) { - return parseQueryString(queryString)[param]; + return parseQueryString$1(queryString)[param]; } @@ -3643,7 +3643,7 @@ function closePort(port) { * @implements {ActivityPort} * @implements {ActivityMessagingPort} */ -class ActivityIframePort { +class ActivityIframePort$1 { /** * @param {!HTMLIFrameElement} iframe @@ -4346,7 +4346,7 @@ class ActivityWindowRedirectPort { * as a singleton. It can start activities of all modes: iframe, popup, and * redirect. */ -class ActivityPorts { +class ActivityPorts$1 { /** * @param {!Window} win @@ -4389,7 +4389,7 @@ class ActivityPorts { * @return {!Promise} */ openIframe(iframe, url, opt_args) { - const port = new ActivityIframePort(iframe, url, opt_args); + const port = new ActivityIframePort$1(iframe, url, opt_args); return port.connect().then(() => port); } @@ -4567,8 +4567,8 @@ class ActivityPorts { var activityPorts = { - ActivityPorts, - ActivityIframePort, + ActivityPorts: ActivityPorts$1, + ActivityIframePort: ActivityIframePort$1, ActivityMessagingPort, ActivityMode, ActivityOpenOptions, @@ -4653,7 +4653,7 @@ class ErrorUtils { */ /** @const {!Object} */ -const iframeAttributes = { +const iframeAttributes$2 = { 'frameborder': '0', 'scrolling': 'no', }; @@ -4690,7 +4690,7 @@ class ActivityIframeView extends View { this.iframe_ = /** @type {!HTMLIFrameElement} */ (createElement( this.doc_, 'iframe', - iframeAttributes + iframeAttributes$2 )); /** @private @const {!../components/activities.ActivityPorts} */ @@ -5422,7 +5422,7 @@ class UserData { /** */ -class SubscribeResponse$1 { +class SubscribeResponse { /** * @param {string} raw * @param {!PurchaseData} purchaseData @@ -5465,7 +5465,7 @@ class SubscribeResponse$1 { * @return {!SubscribeResponse} */ clone() { - return new SubscribeResponse$1( + return new SubscribeResponse( this.raw, this.purchaseData, this.userData, @@ -5972,7 +5972,7 @@ let cache; * @param {string} url * @return {!LocationDef} */ -function parseUrl$1(url) { +function parseUrl(url) { if (!a) { a = /** @type {!HTMLAnchorElement} */ (self.document.createElement('a')); cache = self.UrlCache || (self.UrlCache = Object.create(null)); @@ -6050,7 +6050,7 @@ function parseUrlWithA(a, url) { * @param {string} query The URL query string. * @return {!Object} */ -function parseQueryString$1(query) { +function parseQueryString(query) { if (!query) { return {}; } @@ -6113,8 +6113,8 @@ function getCanonicalUrl(doc) { return (node && node.href) || ''; } -const PARSED_URL = parseUrl$1(self.window.location.href); -const PARSED_REFERRER = parseUrl$1(self.document.referrer); +const PARSED_URL = parseUrl(self.window.location.href); +const PARSED_REFERRER = parseUrl(self.document.referrer); /** * True for Google domains @@ -6180,7 +6180,7 @@ const CACHE_KEYS = { * @return {string} */ function feOrigin() { - return parseUrl$1('https://news.google.com').origin; + return parseUrl('https://news.google.com').origin; } /** @@ -6209,7 +6209,7 @@ function feUrl(url, prefix = '') { url = feCached('https://news.google.com' + prefix + '/swg/_/ui/v1' + url); // Optionally add jsmode param. This allows us to test against "aggressively" compiled Boq JS. - const query = parseQueryString$1(self.location.hash); + const query = parseQueryString(self.location.hash); const boqJsMode = query['swg.boqjsmode']; if (boqJsMode !== undefined) { url = addQueryParam(url, 'jsmode', boqJsMode); @@ -6232,7 +6232,7 @@ function feCached(url) { */ function feArgs(args) { return Object.assign(args, { - '_client': 'SwG 0.1.22.150', + '_client': 'SwG 0.1.22.151', }); } @@ -6297,7 +6297,7 @@ const RecurrenceMapping = { * @param {string} sku * @return {!EventParams} */ -function getEventParams(sku) { +function getEventParams$1(sku) { return new EventParams([, , , , sku]); } @@ -6378,7 +6378,7 @@ class PayStartFlow { this.eventManager_.logSwgEvent( AnalyticsEvent.ACTION_PAYMENT_FLOW_STARTED, true, - getEventParams(swgPaymentRequest['skuId']) + getEventParams$1(swgPaymentRequest['skuId']) ); PayCompleteFlow.waitingForPayClient_ = true; this.payClient_.start( @@ -6430,7 +6430,7 @@ class PayCompleteFlow { eventManager.logSwgEvent( AnalyticsEvent.ACTION_PAYMENT_COMPLETE, true, - getEventParams(sku || '') + getEventParams$1(sku || '') ); flow.start(response); }, @@ -6502,7 +6502,7 @@ class PayCompleteFlow { this.eventManager_.logSwgEvent( AnalyticsEvent.IMPRESSION_ACCOUNT_CHANGED, true, - getEventParams(this.sku_ || '') + getEventParams$1(this.sku_ || '') ); this.deps_.entitlementsManager().reset(true); this.response_ = response; @@ -6561,7 +6561,7 @@ class PayCompleteFlow { this.eventManager_.logSwgEvent( AnalyticsEvent.ACTION_ACCOUNT_CREATED, true, - getEventParams(this.sku_ || '') + getEventParams$1(this.sku_ || '') ); this.deps_.entitlementsManager().unblockNextNotification(); this.readyPromise_.then(() => { @@ -6578,7 +6578,7 @@ class PayCompleteFlow { this.eventManager_.logSwgEvent( AnalyticsEvent.ACTION_ACCOUNT_ACKNOWLEDGED, true, - getEventParams(this.sku_ || '') + getEventParams$1(this.sku_ || '') ); this.deps_.entitlementsManager().setToastShown(true); }); @@ -6688,7 +6688,7 @@ function parseSubscriptionResponse(deps, data, completeHandler) { throw new Error('unexpected payment response'); } raw = JSON.stringify(/** @type {!JsonObject} */ (swgData)); - return new SubscribeResponse$1( + return new SubscribeResponse( raw, parsePurchaseData(swgData), parseUserData(swgData), @@ -6768,7 +6768,7 @@ function parseSkuFromPurchaseDataSafe(purchaseData) { * @param {string} sku * @return {!EventParams} */ -function getEventParams$1(sku) { +function getEventParams(sku) { return new EventParams([, , , , sku]); } @@ -6881,7 +6881,7 @@ class OffersFlow { this.eventManager_.logSwgEvent( AnalyticsEvent.ACTION_OFFER_SELECTED, true, - getEventParams$1(sku) + getEventParams(sku) ); new PayStartFlow(this.deps_, subscriptionRequest).start(); } @@ -7005,14 +7005,14 @@ class SubscribeOptionFlow { .triggerFlowCanceled(SubscriptionFlows.SHOW_SUBSCRIBE_OPTION); }); this.activityIframeView_.on( - SubscribeResponse, + SubscribeResponse$1, this.maybeOpenOffersFlow_.bind(this) ); this.activityIframeView_.acceptResult().then( (result) => { const data = result.data; - const response = new SubscribeResponse(); + const response = new SubscribeResponse$1(); if (data['subscribe']) { response.setSubscribe(true); } @@ -7192,7 +7192,7 @@ class ActivityPortDeprecated { /** * @implements {ActivityPortDef} */ -class ActivityIframePort$1 { +class ActivityIframePort { /** * @param {!HTMLIFrameElement} iframe * @param {string} url @@ -7325,7 +7325,7 @@ class ActivityIframePort$1 { } } -class ActivityPorts$1 { +class ActivityPorts { /** * @param {!../runtime/deps.DepsDef} deps */ @@ -7351,7 +7351,7 @@ class ActivityPorts$1 { 'analyticsContext': context.toArray(), 'publicationId': pageConfig.getPublicationId(), 'productId': pageConfig.getProductId(), - '_client': 'SwG 0.1.22.150', + '_client': 'SwG 0.1.22.151', 'supportsEventManager': true, }, args || {} @@ -7366,7 +7366,7 @@ class ActivityPorts$1 { * @return {!Promise} */ openActivityIframePort_(iframe, url, args) { - const activityPort = new ActivityIframePort$1(iframe, url, this.deps_, args); + const activityPort = new ActivityIframePort(iframe, url, this.deps_, args); return activityPort.connect().then(() => activityPort); } @@ -7825,7 +7825,7 @@ function getExperiments(win) { experimentMap = {}; let combinedExperimentString = experimentsString; try { - const query = parseQueryString$1(win.location.hash); + const query = parseQueryString(win.location.hash); const experimentStringFromHash = query['swg.experiments']; if (experimentStringFromHash) { combinedExperimentString += ',' + experimentStringFromHash; @@ -8047,7 +8047,7 @@ class AnalyticsService { 'iframe', {} )); - setImportantStyles(this.iframe_, iframeStyles); + setImportantStyles$1(this.iframe_, iframeStyles); this.doc_.getBody().appendChild(this.getElement()); /** @private @type {!boolean} */ @@ -8192,11 +8192,11 @@ class AnalyticsService { } else { context.setTransactionId(getUuid()); } - context.setReferringOrigin(parseUrl$1(this.getReferrer_()).origin); - context.setClientVersion('SwG 0.1.22.150'); + context.setReferringOrigin(parseUrl(this.getReferrer_()).origin); + context.setClientVersion('SwG 0.1.22.151'); context.setUrl(getCanonicalUrl(this.doc_)); - const utmParams = parseQueryString$1(this.getQueryString_()); + const utmParams = parseQueryString(this.getQueryString_()); const campaign = utmParams['utm_campaign']; const medium = utmParams['utm_medium']; const source = utmParams['utm_source']; @@ -8530,7 +8530,7 @@ class SmartSubscriptionButtonApi { * @return {!Element} */ start() { - setImportantStyles(this.iframe_, { + setImportantStyles$1(this.iframe_, { 'opacity': 1, 'position': 'absolute', 'top': 0, @@ -8654,7 +8654,7 @@ function getLanguageCodeFromElement(element) { /** @type {!Object} */ const TITLE_LANG_MAP = { 'en': 'Subscribe with Google', - 'ar': 'Google اشترك مع', + 'ar': 'Google اشترك مع', 'de': 'Abonnieren mit Google', 'es': 'Suscríbete con Google', 'es-latam': 'Suscríbete con Google', @@ -9440,7 +9440,7 @@ class DeferredAccountFlow { // Start the "sync" flow. creatingFlow.start( - new SubscribeResponse$1( + new SubscribeResponse( '', // raw field doesn't matter in this case purchaseDataList[0], userData, @@ -9453,7 +9453,7 @@ class DeferredAccountFlow { } } -const CSS = "body{padding:0;margin:0}swg-container,swg-loading,swg-loading-animate,swg-loading-image{display:block}swg-loading-container{width:100%!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-align:center!important;align-items:center!important;-ms-flex-pack:center!important;justify-content:center!important;min-height:148px!important;height:100%!important;bottom:0!important;margin-top:5px!important;z-index:2147483647!important}@media (min-height:630px), (min-width:630px){swg-loading-container{width:560px!important;margin-left:35px!important;border-top-left-radius:8px!important;border-top-right-radius:8px!important;background-color:#fff!important;box-shadow:0 1px 1px rgba(60,64,67,.3),0 1px 4px 1px rgba(60,64,67,.15)!important}}swg-loading{z-index:2147483647!important;width:36px;height:36px;overflow:hidden;animation:mspin-rotate 1568.63ms linear infinite}swg-loading-animate{animation:mspin-revrot 5332ms steps(4) infinite}swg-loading-image{background-image:url(https://news.google.com/swg/js/v1/loader.svg);background-size:100%;width:11664px;height:36px;animation:swg-loading-film 5332ms steps(324) infinite}@keyframes swg-loading-film{0%{transform:translateX(0)}to{transform:translateX(-11664px)}}@keyframes mspin-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes mspin-revrot{0%{transform:rotate(0deg)}to{transform:rotate(-1turn)}}\n/*# sourceURL=/./src/ui/ui.css*/"; +const CSS$1 = "body{padding:0;margin:0}swg-container,swg-loading,swg-loading-animate,swg-loading-image{display:block}swg-loading-container{width:100%!important;display:-ms-flexbox!important;display:flex!important;-ms-flex-align:center!important;align-items:center!important;-ms-flex-pack:center!important;justify-content:center!important;min-height:148px!important;height:100%!important;bottom:0!important;margin-top:5px!important;z-index:2147483647!important}@media (min-height:630px), (min-width:630px){swg-loading-container{width:560px!important;margin-left:35px!important;border-top-left-radius:8px!important;border-top-right-radius:8px!important;background-color:#fff!important;box-shadow:0 1px 1px rgba(60,64,67,.3),0 1px 4px 1px rgba(60,64,67,.15)!important}}swg-loading{z-index:2147483647!important;width:36px;height:36px;overflow:hidden;animation:mspin-rotate 1568.63ms linear infinite}swg-loading-animate{animation:mspin-revrot 5332ms steps(4) infinite}swg-loading-image{background-image:url(https://news.google.com/swg/js/v1/loader.svg);background-size:100%;width:11664px;height:36px;animation:swg-loading-film 5332ms steps(324) infinite}@keyframes swg-loading-film{0%{transform:translateX(0)}to{transform:translateX(-11664px)}}@keyframes mspin-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes mspin-revrot{0%{transform:rotate(0deg)}to{transform:rotate(-1turn)}}\n/*# sourceURL=/./src/ui/ui.css*/"; /** * Copyright 2018 The Subscribe with Google Authors. All Rights Reserved. @@ -9578,14 +9578,14 @@ class FriendlyIframe { * @param {string} curve - transition function for the animation. * @return {!Promise} Promise which resolves once the animation is done playing. */ -function transition(el, props, durationMillis, curve) { +function transition$1(el, props, durationMillis, curve) { const win = el.ownerDocument.defaultView; const previousTransitionValue = el.style.transition || ''; return new Promise((resolve) => { win.setTimeout(() => { win.setTimeout(resolve, durationMillis); const tr = `${durationMillis}ms ${curve}`; - setImportantStyles( + setImportantStyles$1( el, Object.assign( { @@ -9596,7 +9596,7 @@ function transition(el, props, durationMillis, curve) { ); }); }).then(() => { - setImportantStyles(el, { + setImportantStyles$1(el, { 'transition': previousTransitionValue, }); }); @@ -9618,7 +9618,7 @@ function transition(el, props, durationMillis, curve) { * limitations under the License. */ -class Graypane { +class Graypane$1 { /** * @param {!../model/doc.Doc} doc * @param {number} zIndex @@ -9631,7 +9631,7 @@ class Graypane { this.fadeBackground_ = this.doc_ .getWin() .document.createElement('swg-popup-background'); - setImportantStyles(this.fadeBackground_, { + setImportantStyles$1(this.fadeBackground_, { 'z-index': zIndex, 'display': 'none', 'position': 'fixed', @@ -9677,12 +9677,12 @@ class Graypane { * @return {!Promise|undefined} */ show(animated = true) { - setImportantStyles(this.fadeBackground_, { + setImportantStyles$1(this.fadeBackground_, { 'display': 'block', 'opacity': animated ? 0 : 1, }); if (animated) { - return transition( + return transition$1( this.fadeBackground_, { 'opacity': 1, @@ -9700,7 +9700,7 @@ class Graypane { */ hide(animated = true) { if (animated) { - return transition( + return transition$1( this.fadeBackground_, { 'opacity': 0, @@ -9708,10 +9708,10 @@ class Graypane { 300, 'ease-out' ).then(() => { - setImportantStyles(this.fadeBackground_, {'display': 'none'}); + setImportantStyles$1(this.fadeBackground_, {'display': 'none'}); }); } - setImportantStyles(this.fadeBackground_, {'display': 'none'}); + setImportantStyles$1(this.fadeBackground_, {'display': 'none'}); } } @@ -10063,14 +10063,14 @@ class Dialog { }); /** @private @const {!Graypane} */ - this.graypane_ = new Graypane(doc, Z_INDEX - 1); + this.graypane_ = new Graypane$1(doc, Z_INDEX - 1); const modifiedImportantStyles = Object.assign( {}, rootElementImportantStyles, importantStyles ); - setImportantStyles(this.iframe_.getElement(), modifiedImportantStyles); + setImportantStyles$1(this.iframe_.getElement(), modifiedImportantStyles); setStyles(this.iframe_.getElement(), styles); @@ -10113,7 +10113,7 @@ class Dialog { this.graypane_.attach(); if (hidden) { - setImportantStyles(iframe.getElement(), { + setImportantStyles$1(iframe.getElement(), { 'visibility': 'hidden', 'opacity': 0, }); @@ -10148,7 +10148,7 @@ class Dialog { const iframeDoc = /** @type {!HTMLDocument} */ (this.iframe_.getDocument()); // Inject Google fonts in section of the iframe. - injectStyleSheet(resolveDoc(iframeDoc), CSS); + injectStyleSheet(resolveDoc(iframeDoc), CSS$1); // Add Loading indicator. this.loadingView_ = new LoadingView(iframeDoc); @@ -10170,7 +10170,7 @@ class Dialog { if (animated) { animating = this.animate_(() => { this.graypane_.hide(/* animate */ true); - return transition( + return transition$1( this.getElement(), { 'transform': 'translateY(100%)', @@ -10268,7 +10268,7 @@ class Dialog { * @return {!Promise} */ openView(view) { - setImportantStyles(view.getElement(), resetViewStyles); + setImportantStyles$1(view.getElement(), resetViewStyles); this.entryTransitionToNextView_(); this.view_ = view; @@ -10280,7 +10280,7 @@ class Dialog { } return view.init(this).then(() => { - setImportantStyles(view.getElement(), { + setImportantStyles$1(view.getElement(), { 'opacity': 1, }); if (this.hidden_) { @@ -10299,12 +10299,12 @@ class Dialog { */ show_() { this.animate_(() => { - setImportantStyles(this.getElement(), { + setImportantStyles$1(this.getElement(), { 'transform': 'translateY(100%)', 'opactiy': 1, 'visibility': 'visible', }); - return transition( + return transition$1( this.getElement(), { 'transform': 'translateY(0)', @@ -10337,11 +10337,11 @@ class Dialog { if (newHeight >= oldHeight) { // Expand. animating = this.animate_(() => { - setImportantStyles(this.getElement(), { + setImportantStyles$1(this.getElement(), { 'height': `${newHeight}px`, 'transform': `translateY(${newHeight - oldHeight}px)`, }); - return transition( + return transition$1( this.getElement(), { 'transform': 'translateY(0)', @@ -10353,7 +10353,7 @@ class Dialog { } else { // Collapse. animating = this.animate_(() => { - return transition( + return transition$1( this.getElement(), { 'transform': `translateY(${oldHeight - newHeight}px)`, @@ -10361,7 +10361,7 @@ class Dialog { 300, 'ease-out' ).then(() => { - setImportantStyles(this.getElement(), { + setImportantStyles$1(this.getElement(), { 'height': `${newHeight}px`, 'transform': 'translateY(0)', }); @@ -10369,7 +10369,7 @@ class Dialog { }); } } else { - setImportantStyles(this.getElement(), { + setImportantStyles$1(this.getElement(), { 'height': `${newHeight}px`, }); animating = Promise.resolve(); @@ -10424,7 +10424,7 @@ class Dialog { * Sets the position of the dialog. Currently 'BOTTOM' is set by default. */ setPosition_() { - setImportantStyles(this.getElement(), this.getPositionStyle_()); + setImportantStyles$1(this.getElement(), this.getPositionStyle_()); } /** @@ -10437,7 +10437,7 @@ class Dialog { if (this.inferPosition_() == PositionAt.BOTTOM) { const bottomPadding = newHeight + 20; // Add some extra padding. const htmlElement = this.doc_.getRootElement(); - setImportantStyles(htmlElement, { + setImportantStyles$1(htmlElement, { 'padding-bottom': `${bottomPadding}px`, }); } @@ -10531,7 +10531,7 @@ class DialogManager { this.openPromise_ = null; /** @private @const {!Graypane} */ - this.popupGraypane_ = new Graypane(doc, POPUP_Z_INDEX); + this.popupGraypane_ = new Graypane$1(doc, POPUP_Z_INDEX); /** @private {?Window} */ this.popupWin_ = null; @@ -10867,13 +10867,13 @@ class MeterToastApi { ); const element = this.dialogManager_.getDialog().getElement(); if (mobileMediaQuery.matches) { - setImportantStyles(element, {'box-shadow': IFRAME_BOX_SHADOW}); + setImportantStyles$1(element, {'box-shadow': IFRAME_BOX_SHADOW}); } mobileMediaQuery.addListener((changed) => { if (changed.matches) { - setImportantStyles(element, {'box-shadow': IFRAME_BOX_SHADOW}); + setImportantStyles$1(element, {'box-shadow': IFRAME_BOX_SHADOW}); } else { - setImportantStyles(element, {'box-shadow': ''}); + setImportantStyles$1(element, {'box-shadow': ''}); } }); } @@ -10891,7 +10891,7 @@ class MeterToastApi { .getDialog() .getLoadingView() .getElement(); - setImportantStyles(element, { + setImportantStyles$1(element, { 'width': MINIMIZED_IFRAME_SIZE, 'margin': 'auto', }); @@ -10944,7 +10944,7 @@ const toastImportantStyles = { }; /** @const {!Object} */ -const iframeAttributes$2 = { +const iframeAttributes = { 'frameborder': '0', 'scrolling': 'no', 'class': 'swg-toast', @@ -10979,10 +10979,10 @@ class Toast { this.iframe_ = /** @type {!HTMLIFrameElement} */ (createElement( this.doc_.getWin().document, 'iframe', - iframeAttributes$2 + iframeAttributes )); - setImportantStyles(this.iframe_, toastImportantStyles); + setImportantStyles$1(this.iframe_, toastImportantStyles); /** @private @const {!Promise} */ this.ready_ = new Promise((resolve) => { @@ -11021,12 +11021,12 @@ class Toast { resetStyles(this.iframe_, ['height']); this.animate_(() => { - setImportantStyles(this.iframe_, { + setImportantStyles$1(this.iframe_, { 'transform': 'translateY(100%)', 'opactiy': 1, 'visibility': 'visible', }); - return transition( + return transition$1( this.iframe_, { 'transform': 'translateY(0)', @@ -11078,7 +11078,7 @@ class Toast { return Promise.resolve(); }, 500); - return transition( + return transition$1( this.iframe_, { 'transform': 'translateY(100%)', @@ -11211,6 +11211,50 @@ function analyticsEventToEntitlementResult(event) { return AnalyticsEventToEntitlementResult[event]; } +/** + * Copyright 2020 The Subscribe with Google 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. + */ + +/** + * Returns true if the query string contains fresh Google Article Access (GAA) params. + * @param {string} queryString + * @return {boolean} + */ +function queryStringHasFreshGaaParams(queryString) { + const params = parseQueryString(queryString); + + // Verify GAA params exist. + if ( + !params['gaa_at'] || + !params['gaa_n'] || + !params['gaa_sig'] || + !params['gaa_ts'] + ) { + return false; + } + + // Verify timestamp isn't stale. + const expirationTimestamp = parseInt(params['gaa_ts'], 16); + const currentTimestamp = Date.now() / 1000; + if (expirationTimestamp < currentTimestamp) { + return false; + } + + return true; +} + /** * Copyright 2020 The Subscribe with Google Authors. All Rights Reserved. * @@ -11307,7 +11351,7 @@ class EntitlementsManager { this.deps_ .eventManager() - .registerEventListener(this.handleClientEvent_.bind(this)); + .registerEventListener(this.possiblyPingbackOnClientEvent_.bind(this)); } /** @@ -11397,6 +11441,11 @@ class EntitlementsManager { if (!entitlement || entitlement.source !== GOOGLE_METERING_SOURCE) { return; } + // Verify GAA params are present, otherwise bail since the pingback + // shouldn't happen on non-metering requests. + if (!queryStringHasFreshGaaParams(this.win_.location.search)) { + return; + } this.deps_ .eventManager() @@ -11415,7 +11464,13 @@ class EntitlementsManager { // Listens for events from the event manager and informs // the server about publisher entitlements and non- // consumable Google entitlements. - handleClientEvent_(event) { + possiblyPingbackOnClientEvent_(event) { + // Verify GAA params are present, otherwise bail since the pingback + // shouldn't happen on non-metering requests. + if (!queryStringHasFreshGaaParams(this.win_.location.search)) { + return; + } + // A subset of analytics events are also an entitlement result const result = analyticsEventToEntitlementResult(event.eventType); if (!result) { @@ -11441,7 +11496,6 @@ class EntitlementsManager { default: return; } - this.postEntitlementsRequest_(new EntitlementJwt(), result, source); } @@ -11965,19 +12019,21 @@ class Xhr { * @return {!Promise} */ fetch(input, init) { - // TODO (avimehta): Figure out if CORS needs be handled the way AMP does it. init = setupInit(init); return this.fetch_(input, init) - .then( - (response) => response, - (reason) => { - const targetOrigin = parseUrl$1(input).origin; - throw new Error( - `XHR Failed fetching (${targetOrigin}/...):`, - reason && reason.message - ); - } - ) + .catch((reason) => { + /* + * If the domain is not valid for SwG we return 404 without + * CORS headers and the browser throws a CORS error. + * We include some helpful text in the message to point the + * publisher towards the real problem. + */ + const targetOrigin = parseUrl(input).origin; + throw new Error( + `XHR Failed fetching (${targetOrigin}/...): (Note: a CORS error above may indicate that this domain is not configured for Subscribe with Google)`, + reason && reason.message + ); + }) .then((response) => assertSuccess(response)); } } @@ -12326,7 +12382,13 @@ class XhrFetcher { headers: {'Accept': 'text/plain, application/json'}, credentials: 'include', }); - return this.fetch(url, init).then((response) => response.json()); + return this.fetch(url, init).then((response) => { + return response.text().then((text) => { + // Remove "")]}'\n" XSSI prevention prefix in safe responses. + const cleanedText = text.replace(/^(\)\]\}'\n)/, ''); + return parseJson(cleanedText); + }); + }); } sendPost(url, message) { @@ -13201,7 +13263,7 @@ class OffersApi { * limitations under the License. */ -const MAX_Z_INDEX = 2147483647; +const MAX_Z_INDEX$1 = 2147483647; const Constants = {}; @@ -13326,7 +13388,7 @@ Constants.IFRAME_STYLE = ` overflow: visible; position: fixed; width: 100%; - z-index: ${MAX_Z_INDEX}; + z-index: ${MAX_Z_INDEX$1}; -webkit-appearance: none; left: 0; } @@ -13370,7 +13432,7 @@ Constants.IFRAME_STYLE_CENTER = ` top: 100%; transform: scale(0.8); width: 480px; - z-index: ${MAX_Z_INDEX}; + z-index: ${MAX_Z_INDEX$1}; -webkit-appearance: none; } @media (min-height: 667px) { @@ -13806,10 +13868,10 @@ class PaymentsRequestDelegate { * limitations under the License. */ -const MAX_Z_INDEX$1 = 2147483647; +const MAX_Z_INDEX = 2147483647; -class Graypane$1 { +class Graypane { /** * @param {!Document} doc @@ -13820,8 +13882,8 @@ class Graypane$1 { /** @private @const {!Element} */ this.element_ = doc.createElement(Constants.GPAY_GRAYPANE); - setImportantStyles$1(this.element_, { - 'z-index': MAX_Z_INDEX$1, + setImportantStyles(this.element_, { + 'z-index': MAX_Z_INDEX, 'display': 'none', 'position': 'fixed', 'top': 0, @@ -13853,11 +13915,11 @@ class Graypane$1 { show(popupWindow) { this.popupWindow_ = popupWindow || null; this.doc_.body.appendChild(this.element_); - setImportantStyles$1(this.element_, { + setImportantStyles(this.element_, { 'display': 'block', 'opacity': 0, }); - return transition$1(this.element_, { + return transition(this.element_, { 'opacity': 1, }, 300, 'ease-out'); } @@ -13873,10 +13935,10 @@ class Graypane$1 { // This could be possible after redirect. return; } - return transition$1(this.element_, { + return transition(this.element_, { 'opacity': 0, }, 300, 'ease-out').then(() => { - setImportantStyles$1(this.element_, {'display': 'none'}); + setImportantStyles(this.element_, {'display': 'none'}); this.doc_.body.removeChild(this.element_); }); } @@ -13893,7 +13955,7 @@ class Graypane$1 { * @param {!Element} element * @param {!Object} styles */ -function setImportantStyles$1(element, styles) { +function setImportantStyles(element, styles) { for (const k in styles) { element.style.setProperty(k, styles[k].toString(), 'important'); } @@ -13908,20 +13970,20 @@ function setImportantStyles$1(element, styles) { * @param {string} curve - transition function for the animation. * @return {!Promise} Promise which resolves once the animation is done playing. */ -function transition$1(el, props, durationMillis, curve) { +function transition(el, props, durationMillis, curve) { const win = el.ownerDocument.defaultView; const previousTransitionValue = el.style.transition || ''; return new Promise(resolve => { win.setTimeout(() => { win.setTimeout(resolve, durationMillis); const tr = `${durationMillis}ms ${curve}`; - setImportantStyles$1(el, Object.assign({ + setImportantStyles(el, Object.assign({ 'transition': `transform ${tr}, opacity ${tr}`, }, props)); }); }).then(() => { // Stop transition and make sure that the final properties get set. - setImportantStyles$1(el, Object.assign({ + setImportantStyles(el, Object.assign({ 'transition': previousTransitionValue, }, props)); }); @@ -14753,7 +14815,7 @@ class PaymentsWebActivityDelegate { /** @const {!ActivityPorts} */ this.activities = activities || new activityPorts_1(window); /** @const @private {!Graypane} */ - this.graypane_ = new Graypane$1(window.document); + this.graypane_ = new Graypane(window.document); /** @private {?function(!Promise)} */ this.callback_ = null; /** @@ -15598,10 +15660,10 @@ Dual licensed under the MIT and GPL licenses. */ class Random_uuid {} // Private array of chars to use - var CHARS$1 = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); + var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split(''); Random_uuid.uuid = function (len, radix) { - var chars = CHARS$1, uuid = [], i; + var chars = CHARS, uuid = [], i; radix = radix || chars.length; if (len) { @@ -15631,7 +15693,7 @@ class Random_uuid {} // Private array of chars to use // A more performant, but slightly bulkier, RFC4122v4 solution. We boost performance // by minimizing calls to random() Random_uuid.uuidFast = function() { - var chars = CHARS$1, uuid = new Array(36), rnd=0, r; + var chars = CHARS, uuid = new Array(36), rnd=0, r; for (var i = 0; i < 36; i++) { if (i==8 || i==13 || i==18 || i==23) { uuid[i] = '-'; @@ -17041,7 +17103,7 @@ class Propensity { } } -const CSS$1 = ".swg-dialog,.swg-toast{box-sizing:border-box;background-color:#fff!important}.swg-toast{position:fixed!important;bottom:0!important;max-height:46px!important;z-index:2147483647!important;border:none!important}@media (max-height:640px), (max-width:640px){.swg-dialog,.swg-toast{width:480px!important;left:-240px!important;margin-left:50vw!important;border-top-left-radius:8px!important;border-top-right-radius:8px!important;box-shadow:0 1px 1px rgba(60,64,67,.3),0 1px 4px 1px rgba(60,64,67,.15)!important}}@media (min-width:640px) and (min-height:640px){.swg-dialog{width:630px!important;left:-315px!important;margin-left:50vw!important;background-color:transparent!important;border:none!important}.swg-toast{left:0!important}}@media (max-width:480px){.swg-dialog,.swg-toast{width:100%!important;left:0!important;right:0!important;margin-left:0!important}}\n/*# sourceURL=/./src/components/dialog.css*/"; +const CSS = ".swg-dialog,.swg-toast{box-sizing:border-box;background-color:#fff!important}.swg-toast{position:fixed!important;bottom:0!important;max-height:46px!important;z-index:2147483647!important;border:none!important}@media (max-height:640px), (max-width:640px){.swg-dialog,.swg-toast{width:480px!important;left:-240px!important;margin-left:50vw!important;border-top-left-radius:8px!important;border-top-right-radius:8px!important;box-shadow:0 1px 1px rgba(60,64,67,.3),0 1px 4px 1px rgba(60,64,67,.15)!important}}@media (min-width:640px) and (min-height:640px){.swg-dialog{width:630px!important;left:-315px!important;margin-left:50vw!important;background-color:transparent!important;border:none!important}.swg-toast{left:0!important}}@media (max-width:480px){.swg-dialog,.swg-toast{width:100%!important;left:0!important;right:0!important;margin-left:0!important}}\n/*# sourceURL=/./src/components/dialog.css*/"; /** * Copyright 2018 The Subscribe with Google Authors. All Rights Reserved. @@ -17220,50 +17282,6 @@ class WaitForSubscriptionLookupApi { } } -/** - * Copyright 2020 The Subscribe with Google 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. - */ - -/** - * Returns true if the query string contains fresh Google Article Access (GAA) params. - * @param {string} queryString - * @return {boolean} - */ -function queryStringHasFreshGaaParams(queryString) { - const params = parseQueryString$1(queryString); - - // Verify GAA params exist. - if ( - !params['gaa_at'] || - !params['gaa_n'] || - !params['gaa_sig'] || - !params['gaa_ts'] - ) { - return false; - } - - // Verify timestamp isn't stale. - const expirationTimestamp = parseInt(params['gaa_ts'], 16); - const currentTimestamp = Date.now() / 1000; - if (expirationTimestamp < currentTimestamp) { - return false; - } - - return true; -} - /** * Copyright 2018 The Subscribe with Google Authors. All Rights Reserved. * @@ -17343,7 +17361,7 @@ class ConfiguredRuntime { // WARNING: DepsDef ('this') is being progressively defined below. // Constructors will crash if they rely on something that doesn't exist yet. /** @private @const {!../components/activities.ActivityPorts} */ - this.activityPorts_ = new ActivityPorts$1(this); + this.activityPorts_ = new ActivityPorts(this); /** @private @const {!AnalyticsService} */ this.analyticsService_ = new AnalyticsService(this, this.fetcher_); @@ -17388,7 +17406,7 @@ class ConfiguredRuntime { LinkCompleteFlow.configurePending(this); PayCompleteFlow.configurePending(this); - injectStyleSheet(this.doc_, CSS$1); + injectStyleSheet(this.doc_, CSS); // Report redirect errors if any. this.activityPorts_.onRedirectError((error) => { @@ -17451,6 +17469,11 @@ class ConfiguredRuntime { return this.storage_; } + /** @override */ + clientConfigManager() { + return null; + } + /** @override */ analytics() { return this.analyticsService_; @@ -17813,7 +17836,7 @@ class ConfiguredRuntime { if ( !entitlement || !isSecure(this.win().location) || - !wasReferredByGoogle(parseUrl$1(this.win().document.referrer)) || + !wasReferredByGoogle(parseUrl(this.win().document.referrer)) || !queryStringHasFreshGaaParams(this.win().location.search) ) { return; @@ -17843,4 +17866,4 @@ class ConfiguredRuntime { } } -export { AnalyticsEvent, ClientEvent, ClientEventManagerApi, ConfiguredRuntime, DeferredAccountCreationResponse, Entitlement, Entitlements, EventOriginator, Fetcher, FilterResult, PurchaseData, SubscribeResponse$1 as SubscribeResponse, UserData }; +export { AnalyticsEvent, ClientEvent, ClientEventManagerApi, ConfiguredRuntime, DeferredAccountCreationResponse, Entitlement, Entitlements, EventOriginator, Fetcher, FilterResult, PurchaseData, SubscribeResponse, UserData };