Šimon Toman (Chrenek, Toman a Kotrba): Český přístup k regulaci dodavatelů je jedním z nejpřísnějších

16. 1. 2024
Doba čtení: 7 minut

Sdílet

Autor: Martin Drtina, Internet Info
Geopolitická rovina má významný vliv na postup států v otázce regulace dodavatelů. „Není špatné to regulovat. Špatné je, jak je to navržené,“ říká právník hájící zájmy Huawei. Uvnitř: ROZHOVOR A PODCAST.

Právník Šimon Toman z advokátní kanceláře Chrenek, Toman a Kotrba se problematikou kybernetické bezpečnosti zaobírá od roku 2018. Za tu dobu právní služby poskytoval celé řadě subjektů, na které dopadla nebo dopadne chystaná regulace. Mezi jeho klienty patří i firma Huawei. Té v případě, že zákon projde sněmovnou v navrženém znění, hrozí úplný zákaz podílet se na dodávkách pro tuzemské telekomunikační sítě.

O mechanismu bezpečnosti dodavatelského řetězce i dalších souvisejících otázkách je rozhovor, jehož část jsme přepsali do textu. Celý si jej můžete poslechnout ve formě podcastu na službách, jako je Google Podcast, Apple Podcast, Spotify, nebo přímo zde:

Když víte, jaký odpor u regulátora vyvolává byť jen zmínka o čínských komponentech v tuzemských mobilních sítích, nepřipadáte si jako Ďáblův advokát z filmu Taylora Hackforda?

Možná i trochu připadám a o to víc jsem rád, že dělám to, co dělám. Je to extrémně zajímavá práce a pracuji na otázkách, kterým se moc právníků nevěnuje. A to dělá naši práci velmi zajímavou.

Já mám teď na mysli obhajobu něčeho, co regulátor a s ním i politická reprezentace vnímá jako něco špatného. Přijdete si, že děláte něco špatného?

Rozhodně ne. Myslím si, že každá firma, každá osoba tady má právo na právníka. To z nás také dělá demokratickou zemi. Máme mnoho firem, se kterými úřady nesouhlasí. Většina naší práce je boj proti úřadům, které se nějakým způsobem snaží omezit nebo znepříjemnit život našim klientům. Takže tohle není nic nového.

Huawei není jedinou firmou na opačné straně barikády oproti tuzemskému regulátorovi, jejíž zájmy jste hájil. Jak se to tak přihodí, že kývnete na žádost takovýchto klientů, abyste je zastupoval?

Jak říkám, když máte možnost pracovat na něčem zajímavém, je hloupé na to nekývnout. Je důležité si uvědomit, že my nejsme soudci. Nejsem tu od toho, abych klientovi říkal, co dělá špatně, abych ho nějakým způsobem soudil. Já jsem od toho, abych hájil jeho zájmy. Jak jste řekl, mám v této oblasti více klientů, nemůžu je jmenovat (kvůli advokátní mlčenlivosti – pozn. red.), ale regulace dopadá na mnoho společností, velkých, významných, které se o to zajímají. A nejde zdaleka jen o Huawei.

Právními otázkami kolem kyberbezpečnosti se zabýváte už řadu let. Jak vnímáte posun regulace v této oblasti? 

To je těžká otázka. Jak zní z mnoha stran, je to důležité téma. Musí se to řešit. Ale společně s tím se musí řešit řada dalších témat. Já jenom doufám, že tahle regulace nebude dalším hřebíkem do rakve mnoha našich klientů a společností.

Jak to myslíte? Těch regulací nebo překážek je už takové množství, že to některým brání svobodně podnikat?

Svobodně ne, ale myslím to tak, že když jsou různé konference na téma kybernetické bezpečnosti NIS2, na kterých i já často vystupuji, jsou tam pozváni i zástupci velkých firem, mobilních operátorů, bank, a jsou tam často také zástupci těch poradenských firem, jako jsme my, právníci. A ti všichni mluví o tom, jak je kybernetická bezpečnost strašně důležitá, jak jim uložit povinnosti, jak to ty firmy musí dělat. Musíme si uvědomit, že třeba mobilní operátoři do toho mají možnost investovat stovky milionů, platit ty největší experty, co jsou k dispozici. 

Drtivá většina menších podnikatelů ale na to není připravena. Řítí se na ně velký objem regulace. Třeba v oblasti energetiky. Musíte být zelení, inkluzivní, musíte mít to či ono, já tam s nimi sedím a už se jim bojím říct, že je tu ještě další směrnice. Pak už mají jenom hlavu zalomenou v dlaních a vůbec nevědí, kam dřív. Být statutárem v této době jakékoliv firmy je velmi obtížné.

Pojďme se podívat na směrnici NIS2. Ta preferuje koordinovaný celoevropský postup v otázce regulace čínských výrobců. NÚKIB si chce o těchto otázkách rozhodovat sám, izolovaně. Proč tento přístup?

To téma není až tak kyberbezpečnostní, jako spíše geopolitické. Ukazuje to, jak k tomu každá země přistupuje jinak. To je dáno tím, že každá země má jiný vztah s Čínou, jiný s Amerikou a dalšími státy. Geopolitika na to má významný dopad. Ovlivňuje i to, jak k tomu přistupujeme my nebo jiné země. NÚKIB se rozhodl to pojmout nějakým způsobem, má k tomu samozřejmě podporu. Nemyslím si, že je špatné to regulovat. Špatné je, jak je to navržené.

A je tedy namístě, že otázku bezpečnosti dodavatelského řetězce řešíme na národní úrovni? Neměla by být řešena celoevropsky? 

Je vždycky lepší mít jednotný postup. Pro podnikatele je nejdůležitější předvídatelnost. A tady ji nemám, když nevím, jak k tomu přistoupí Česko, Slovensko a Rakousko. Každý ten přístup může být jiný. Takže by bylo skvělé, kdyby posuzování dodavatelů bylo nějakým způsobem harmonizováno a každý k tomu přistupoval stejně. Nevím ale, jestli je to reálné. Pokud musíme řešit bezpečnost dodavatelského řetězce a stát je toho názoru, že ji musíme řešit rychle, nezbývá nám nic jiného, než to řešit na národní úrovni.

Zmínili jsme okolní státy, jak se k této otázce staví ostatní země?

Padesát na padesát. Jsou státy, které to vůbec neřeší. Vedle nich jsou země, které přistoupily k okamžitému zákazu čínských dodavatelů. A pak státy, které k tomu přistupují – dovolím si říct – chytře. Třeba regulují nějaké části, další neregulují, nastavily smysluplný proces, jak k tomu přistoupit. Bylo by obtížné najít dva stejné přístupy.

Jak jsme na tom my?

Návrh náš je jeden z těch nejpřísnějších. Umožňuje největší zásah. Většina států zásah do dodavatelského řetězce omezila na nějaký scope a nastavila tam mnoho kontrolních mechanismů. V řadě zemí ve finále rozhoduje vláda. V některých pak mají svou roli v tom procesu soukromí podnikatelé. Ze zákona tam vznikly pracovní skupiny, které jsou diskusním partnerem státu a společně se doberou nějakého řešení. Není to jen o tom, jestli zakázat, nezakázat a kde. Je to také o tom, jaký přístup stát zvolil. Jak pomoci podnikatelům, když na ten zákaz případně přistoupí.

Teď mluvíte o kompenzacích?

Nejen o kompenzacích. Mluvím i o dlouhodobé strategii. Kompenzace jsou jedna věc. V Anglii nebo Americe, kde došlo k zákazu, to stát nějakým způsobem kompenzoval. Ale také ta země vytváří dlouhodobější strategie, aby vyřešila problém, když se dodavatel zakáže. Bohužel o tom se moc nemluví. Ti dodavatelé jsou tři, možná čtyři. A když jednoho z nich zakážeme, vytvoří to významný problém.

Jaký? Nebudou dodávky, bude chybět substituce těch zakázaných prvků? 

Těch problémů může být víc. V první řadě vendor lock. Když vypisuji soutěž a ze tří dodavatelů mi jednoho zakážou, ti dva zbývající samozřejmě extrémně zdraží. Když to udělá více zemí naráz, ti zbylí dodavatelé nebudou mít co dodávat. Bude chybět zboží. A pak také někteří dodavatelé, o kterých se mluví, mají kvalitnější výrobky, co se třeba energetické náročnosti týče. Takže se nám zvednou náklady na energie. Samozřejmě žijeme v době, kdy jsou dodavatelské řetězce neskutečně propojené. Jestli se nepletu, Huawei má obnovenou licenční smlouvu s Ericssonem. A Ericsson taky vyrábí v Číně.

Společenská poptávka je, že si lidé nepřejí, aby jejich komunikace, mobilní sítě byly nějakým způsobem ohroženy. Jak tedy tomu pomoci? 

Ano, to si nepřeju ani já. A teď jde o to, co je ohrožuje. Když dochází ke směně majetku, nebo když stát něco prodává, tak se na to dělá tisíc znaleckých posudků, úřady k tomu něco řeknou, ministerstva taky. Je to proces na několik let. Vedle toho máme proces, kde stát zvažuje nějaký mechanismus, který by umožňoval plošný zákaz. A já jsem neviděl žádné znalecké posudky, žádné tisícistránkové materiály, které by tuto problematiku řešily. Naopak. Slýchám ze strany soukromého sektoru: nikdo s námi nediskutuje, nikdo s námi o tom nemluví. Moje role není úplně vymýšlet, jak tento problém vyřešit. Ale bez dostatečných analýz nenajdeme nejlepší řešení.

CIF25 SE debata

V podcastu jsme dále rozebrali důvody, proč by stávající úprava prověřování bezpečnosti dodavatelského řetězce měla být z návrhu odstraněna, když je to stále jen potenciální možnost NÚKIBu a na stole v tuto chvíli není žádné bezprostřední nebezpečí, že čínští dodavatelé pro tuzemské mobilní sítě budou zakázáni. Rozebrali jsme také rozpory, s nimiž byl zákon předložen Legislativní radě vlády, a odhadli, jak se bude jeho schvalování dál vyvíjet. 

Celý rozhovor si poslechněte na svých oblíbených podcastových aplikacích, nebo přímo zde:

  • Chcete mít Lupu bez bannerů?
  • Chcete dostávat speciální týdenní newsletter o zákulisí českého internetu?
  • Chcete mít k dispozici strojové přepisy podcastů?
  • Chcete získat slevu 1 000 Kč na jednu z našich konferencí?

Staňte se naším podporovatelem

Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Redaktor serveru Lupa.cz se zaměřením na telekomunikace, média, IT a právo. Dříve šéfredaktor Právního rádce a mluvčí Českého telekomunikačního úřadu.

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »