Как переопределить функцию предупреждения JavaScript внутри iframe до того, как она закончила загрузку? - PullRequest
0 голосов
/ 11 января 2019

Я использую браузер безголового хрома с призраком (https://github.com/BBC-News/wraith). Проблема - это когда у меня открывается страница, предупреждение сбой с призраком

ERROR: unexpected alert open: {Alert text : Bla bla bla.}
  (Session info: headless chrome=71.0.3578.98)
  (Driver info: chromedriver=71.0.3578.33 (269aa0e3f0db08097f0fe231c7e6be200b6939f7),platform=Mac OS X 10.13.6 x86_64)

Это то, что я пытался, но до сих пор не получилось:

const BACKEND_USERNAME = "";
const BACKEND_PASSWORD = "";

function resizeIFrameToFitContent(iFrame) {
    iFrame.width = iFrame.contentWindow.document.body.scrollWidth;
    iFrame.height = iFrame.contentWindow.document.body.scrollHeight;
}


var original_url_asked = document.referrer;
if (typeof jQuery !== 'undefined') {//maybe 500 or 404 page
    $(document).ready(function () {
        //we ended up on login page, let's login
        $('body > div:nth-child(23) > div.backend_right_content > div > div > form > input[type="password"]:nth-child(3)').prop('value', BACKEND_PASSWORD);
        $('body > div:nth-child(23) > div.backend_right_content > div > div > form > input[type="text"]:nth-child(1)').prop('value', BACKEND_USERNAME);
        $('body > div:nth-child(23) > div.backend_right_content > div > div > form > input[type="submit"]:nth-child(5)').click();//submit form

        //we are logged in
        $('body').empty();//clear all the stuff
        //since we can't redirect, we'll open a full page iframe with the url we wanted to see initially
        $('body').append('<iframe id="ifr" width="100%" height="100%" frameborder="0" src="" ></iframe>');

        //load the original_url finally
        $("#ifr").attr("src", original_url_asked);//cannot redirect or wraith complains


        //hide the menu and other elements, for smaller screenshots
        $('#ifr').on('load', function () {
            $('#ifr').contents().find('div.backend_left, div.backend_right_top').remove();
            resizeIFrameToFitContent(document.getElementById('ifr'));
        });
    });
}

//important or wraith will not understand it is ready to take a screenshot
var callback = arguments[arguments.length - 1];
setTimeout(callback, 20000);//wait for page to load

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Вы не можете запретить окно предупреждений с помощью JavaScript, так как к тому времени, когда wraith выполняет сценарий before_capture, всплывающее окно с предупреждением уже существует. Таким образом, wraith пытается выполнить JavaScript, оставляя всплывающее окно с предупреждением открытым, веб-драйвер вызывает ошибку, с которой вы столкнулись.

Вы можете переключиться на phantomjs, чтобы решить эту проблему, но если вы хотите придерживаться селена без хрома и wraith, вам нужно исправить wraith, чтобы правильно обрабатывать модальные всплывающие окна.

Файл : {Каталог установки Ruby} \ lib \ ruby ​​\ gems \ 2.6.0 \ gems \ wraith-4.2.3 \ lib \ wraith \ save_images.rb
Линия : 129

driver.navigate.to url
# patch to handle rogue alert popups at page load
while true
  begin
    driver.switch_to.alert.dismiss
  rescue
    break
  end
end
# patch end
driver.execute_async_script(File.read(global_before_capture)) if global_before_capture

Цикл while будет отклонять столько всплывающих окон, которые он обнаружит при переходе страницы на ваш URL, а затем запускать сценарий before_capture.

0 голосов
/ 14 января 2019

Если у вас есть доступ к перекрестному источнику iframe, вы можете переопределить встроенную функцию alert следующим образом:

<iframe id="ifr" src="about:blank"></iframe>
<script type="text/javascript">
var iframe = document.getElementById('ifr');

iframe.addEventListener('load', function(event)
{
    iframe.contentWindow.alert = function(s){console.log(s)};
});

iframe.src = 'iframe.html';
</script>

Код от iframe.html

<script type="text/javascript">
alert('iframe'); // this will always native function and you can not override it
</script>

<!-- BUT the following message you will get in console: -->
<input type="button" value="try it" onclick="alert('Your native alert was overriden!')">

Теперь вы можете нажать на кнопку в этом iframe, и вы получите сообщение 'Your native alert was overriden!' в вашей консоли.

Другими словами: вы можете переопределить встроенную функцию alert, но у вас нет возможности переопределить ее до загрузки iframe window. У нас нет какого-либо события для этого случая. Только после загрузки iframe window вы можете использовать функцию переопределения. Если вам этого достаточно, вы можете использовать его.

Но что-то большее вы не можете сделать.

Что важно понять:

Всегда после установки из нового src для вашего iframe iframe будет загружать оригинальную (нативную) функцию alert. И из-за этого вы должны переопределять его всегда после загрузки нового сайта в ваш iframe.

Альтернативное решение

Спасибо подсказке от пользователя Munim Munna в комментарии у нас есть идеальное решение: Вы можете добавить sandbox="allow-forms allow-same-origin allow-scripts" в качестве атрибута к вашему iframe следующим образом:

<iframe id="ifr" src="about:blank" sandbox="allow-forms allow-same-origin allow-scripts"></iframe>

и все окна предупреждений будут игнорироваться, если вы не добавите allow-modals в этот список. В консоли в этом случае вы получите сообщение об ошибке:

Игнорируется звонок на 'alert()'. Документ помещен в изолированную программную среду, а ключевое слово allow-modals не задано.

А если кому-то это не нравится, он может переопределить функцию alert, как в первой части этого моего ответа.

...