@@ -16,7 +16,6 @@ import {
1616 createFrameFor ,
1717 isJsonOrObj ,
1818 objOrParseJson ,
19- redispatch ,
2019} from '../../../src/iframe-video' ;
2120import { VideoEvents_Enum } from '../../../src/video-interface' ;
2221
@@ -27,30 +26,10 @@ const TAG = 'amp-slikeplayer';
2726 */
2827
2928/**
30- @enum {string}
29+ * @enum {string}
3130 * @private
3231 */
3332
34- const CleoEvent = {
35- 'ready' : VideoEvents_Enum . LOAD ,
36- 'play' : VideoEvents_Enum . PLAYING ,
37- 'pause' : VideoEvents_Enum . PAUSE ,
38- 'complete' : VideoEvents_Enum . ENDED ,
39- 'visible' : VideoEvents_Enum . VISIBILITY ,
40- 'seeked' : VideoEvents_Enum . SEEKED ,
41- 'seeking' : VideoEvents_Enum . SEEKING ,
42- 'adStart' : VideoEvents_Enum . AD_START ,
43- 'adEnd' : VideoEvents_Enum . AD_END ,
44- 'adPlay' : VideoEvents_Enum . AD_PLAY ,
45- 'adPause' : VideoEvents_Enum . AD_PAUSE ,
46- 'adSkip' : VideoEvents_Enum . AD_SKIP ,
47- 'adComplete' : VideoEvents_Enum . AD_END ,
48- 'adError' : VideoEvents_Enum . AD_ERROR ,
49- 'adLoaded' : VideoEvents_Enum . AD_LOADED ,
50- 'adImpression' : VideoEvents_Enum . AD_IMPRESSION ,
51- 'adClick' : VideoEvents_Enum . AD_CLICK ,
52- } ;
53-
5433export class AmpSlikeplayer extends AMP . BaseElement {
5534 /** @param {!AmpElement } element */
5635 constructor ( element ) {
@@ -78,7 +57,7 @@ export class AmpSlikeplayer extends AMP.BaseElement {
7857 this . onReadyOnce_ = once ( ( detail ) => this . onReady_ ( detail ) ) ;
7958
8059 /** @private {string} */
81- this . config_ = null ;
60+ this . config_ = '' ;
8261
8362 /** @private {string} */
8463 this . poster_ = '' ;
@@ -100,6 +79,9 @@ export class AmpSlikeplayer extends AMP.BaseElement {
10079
10180 /** @private {number} 0..1 */
10281 this . viewportVisibleThreshold_ = 0 ;
82+
83+ /** @private {string} */
84+ this . targetOrigin_ = '*' ;
10385 }
10486
10587 /** @override */
@@ -127,25 +109,7 @@ export class AmpSlikeplayer extends AMP.BaseElement {
127109 this . poster_ = element . getAttribute ( 'poster' ) || '' ;
128110
129111 // Read optional viewport visibility threshold from data-config
130- if ( this . config_ ) {
131- try {
132- const params = new URLSearchParams ( this . config_ ) ;
133- if ( params . has ( 'viewport' ) ) {
134- let threshold = parseFloat (
135- /** @type {string } */ ( params . get ( 'viewport' ) )
136- ) ;
137- if ( isFinite ( threshold ) ) {
138- if ( threshold > 1 ) {
139- threshold = threshold / 100 ; // percent -> ratio
140- }
141- this . viewportVisibleThreshold_ = Math . max (
142- 0 ,
143- Math . min ( 1 , threshold )
144- ) ;
145- }
146- }
147- } catch { }
148- }
112+ this . parseViewportThreshold_ ( ) ;
149113
150114 installVideoManagerForDoc ( element ) ;
151115 const videoManager = Services . videoManagerForDoc ( element ) ;
@@ -180,11 +144,7 @@ export class AmpSlikeplayer extends AMP.BaseElement {
180144
181145 /** @override */
182146 layoutCallback ( ) {
183- let src = `${ this . baseUrl_ } #apikey=${ this . apikey_ } &videoid=${ this . videoid_ } &baseurl=${ this . win . location . origin } ` ;
184-
185- if ( this . config_ ) {
186- src = `${ this . baseUrl_ } #apikey=${ this . apikey_ } &videoid=${ this . videoid_ } &${ this . config_ } &baseurl=${ this . win . location . origin } ` ;
187- }
147+ const src = this . buildIframeSrc_ ( ) ;
188148
189149 const frame = disableScrollingOnIframe (
190150 createFrameFor ( this , src , this . element . id )
@@ -252,11 +212,7 @@ export class AmpSlikeplayer extends AMP.BaseElement {
252212 * @private
253213 */
254214 onMessage_ ( messageEvent ) {
255- if (
256- ! this . iframe_ ||
257- ! messageEvent ||
258- messageEvent . source != this . iframe_ . contentWindow
259- ) {
215+ if ( ! this . isValidMessage_ ( messageEvent ) ) {
260216 return ;
261217 }
262218
@@ -268,52 +224,14 @@ export class AmpSlikeplayer extends AMP.BaseElement {
268224 const data = objOrParseJson ( messageData ) ;
269225 const event = data [ 'event' ] ;
270226 const detail = data [ 'detail' ] ;
227+
271228 if ( event === 'ready' ) {
272229 detail && this . onReadyOnce_ ( detail ) ;
273230 return ;
274231 }
275232 const { element} = this ;
276- if ( redispatch ( element , event , CleoEvent ) ) {
277- return ;
278- }
279- if ( detail && event ) {
280- switch ( event ) {
281- case 'fullscreen' :
282- break ;
283- case 'meta' :
284- break ;
285- case 'mute' :
286- break ;
287- case 'playedRanges' :
288- break ;
289- case 'time' :
290- const { currentTime} = detail ;
291- this . currentTime_ = currentTime ;
292- break ;
293- case 'adTime' :
294- const { position} = detail ;
295- this . currentTime_ = position ;
296- break ;
297- case 'seeked' :
298- case 'seeking' :
299- // Seek events are handled by the redispatch above
300- break ;
301- case 'adStart' :
302- case 'adEnd' :
303- case 'adPlay' :
304- case 'adPause' :
305- case 'adSkip' :
306- case 'adComplete' :
307- case 'adError' :
308- case 'adLoaded' :
309- case 'adImpression' :
310- case 'adClick' :
311- // Ad events are handled by the redispatch above
312- break ;
313- default :
314- break ;
315- }
316- }
233+ this . handleEventDetail_ ( event , detail ) ;
234+ dispatchCustomEvent ( element , event , detail ) ;
317235 }
318236 /**
319237 * @override
@@ -364,13 +282,12 @@ export class AmpSlikeplayer extends AMP.BaseElement {
364282
365283 /** @override */
366284 getCurrentTime ( ) {
367- // Not supported.
368- return this . currentTime_ || 0 ;
285+ return this . currentTime_ ;
369286 }
370287
371288 /** @override */
372289 getDuration ( ) {
373- return this . duration_ || 1 ;
290+ return this . duration_ ;
374291 }
375292
376293 /** @override */
@@ -384,7 +301,7 @@ export class AmpSlikeplayer extends AMP.BaseElement {
384301 }
385302 /**
386303 * @param {string } method
387- * @param {string } [optParams]
304+ * @param {* } [optParams]
388305 * @private
389306 */
390307 postMessage_ ( method , optParams ) {
@@ -397,7 +314,7 @@ export class AmpSlikeplayer extends AMP.BaseElement {
397314 'method' : method ,
398315 'optParams' : optParams ,
399316 } ) ,
400- '*'
317+ this . targetOrigin_
401318 ) ;
402319 } ) ;
403320 }
@@ -423,6 +340,125 @@ export class AmpSlikeplayer extends AMP.BaseElement {
423340 pauseCallback ( ) {
424341 this . pause ( ) ;
425342 }
343+
344+ /**
345+ * @private
346+ * @return {string }
347+ */
348+ buildIframeSrc_ ( ) {
349+ this . setTargetOrigin_ ( ) ;
350+
351+ const params = this . buildUrlParams_ ( ) ;
352+ return `${ this . baseUrl_ } #${ params . join ( '&' ) } ` ;
353+ }
354+
355+ /**
356+ * @private
357+ */
358+ setTargetOrigin_ ( ) {
359+ try {
360+ const url = new URL ( this . baseUrl_ ) ;
361+ this . targetOrigin_ = url . origin ;
362+ } catch {
363+ // Keep default target origin
364+ }
365+ }
366+
367+ /**
368+ * @private
369+ * @return {!Array<string> }
370+ */
371+ buildUrlParams_ ( ) {
372+ const params = [
373+ `apikey=${ encodeURIComponent ( this . apikey_ ) } ` ,
374+ `videoid=${ encodeURIComponent ( this . videoid_ ) } ` ,
375+ ] ;
376+
377+ const extra = this . normalizeConfig_ ( ) ;
378+ if ( extra ) {
379+ params . push ( extra ) ;
380+ }
381+
382+ const origin = this . win . location ?. origin ;
383+ if ( origin ) {
384+ params . push ( `baseurl=${ encodeURIComponent ( origin ) } ` ) ;
385+ }
386+
387+ return params ;
388+ }
389+
390+ /**
391+ * @private
392+ * @return {string }
393+ */
394+ normalizeConfig_ ( ) {
395+ return ( this . config_ || '' ) . trim ( ) . replace ( / ^ [ # ? & ] + / , '' ) ;
396+ }
397+
398+ /**
399+ * @private
400+ */
401+ parseViewportThreshold_ ( ) {
402+ if ( ! this . config_ ) {
403+ return ;
404+ }
405+
406+ try {
407+ const params = new URLSearchParams ( this . config_ ) ;
408+ if ( ! params . has ( 'viewport' ) ) {
409+ return ;
410+ }
411+
412+ let threshold = parseFloat ( params . get ( 'viewport' ) ) ;
413+ if ( ! isFinite ( threshold ) ) {
414+ return ;
415+ }
416+
417+ // Convert percentage to ratio if needed
418+ if ( threshold > 1 ) {
419+ threshold = threshold / 100 ;
420+ }
421+
422+ this . viewportVisibleThreshold_ = Math . max ( 0 , Math . min ( 1 , threshold ) ) ;
423+ } catch {
424+ // Ignore parsing errors
425+ }
426+ }
427+
428+ /**
429+ * @private
430+ * @param {* } messageEvent
431+ * @return {boolean }
432+ */
433+ isValidMessage_ ( messageEvent ) {
434+ return ! ! (
435+ this . iframe_ &&
436+ messageEvent &&
437+ messageEvent . source === this . iframe_ . contentWindow
438+ ) ;
439+ }
440+
441+ /**
442+ * @private
443+ * @param {string } event
444+ * @param {* } detail
445+ */
446+ handleEventDetail_ ( event , detail ) {
447+ if ( ! detail || ! event ) {
448+ return ;
449+ }
450+
451+ switch ( event ) {
452+ case 'cplVideoTimeUpdate' :
453+ this . currentTime_ = detail . currentTime || 0 ;
454+ break ;
455+ case 'cplAdProgress' :
456+ this . currentTime_ = detail . position || 0 ;
457+ break ;
458+ default :
459+ break ;
460+ }
461+ }
426462}
427463
428464AMP . extension ( TAG , '0.1' , ( AMP ) => {
0 commit comments