Переопределите Element.prototype.attachShadow, используя расширение Chrome - PullRequest
0 голосов
/ 02 марта 2019

Мне нужно получить доступ к DOM веб-компонента с закрытым Shadow DOM для некоторых тестов Selenium.Я прочитал в нескольких ссылках, что вы можете переопределить Element.prototype.attachShadow при запуске документа, чтобы изменить Тень с закрытого на открытый.Для этого я создал расширение Chrome.Ниже мой manifest.json:

{
    "name": "SeleniumTesting",
    "description": "Extension to open closed Shadow DOM for selenium testing",
    "version": "1",
    "author": "SeleniumTesting",
    "manifest_version": 2,
    "permissions": ["downloads", "<all_urls>"],
    "content_scripts": [{
        "matches": ["http://localhost:5000/*"],
        "run_at": "document_start",
        "all_frames": true,
        "js": ["shadowInject.js"]
    }]
}

И мой shadowInject.js

console.log('test');
Element.prototype._attachShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = function () {
    console.log('attachShadow');
    return this._attachShadow( { mode: "open" } );
};

Чтобы протестировать его, я создал свой компонент в ASPNetCore MVCпроект.Ниже мой javascript, который создает пользовательский компонент:

customElements.define('x-element', class extends HTMLElement {
    constructor() {
        super(); 
        this._shadowRoot = this.attachShadow({
            mode: 'closed'
        });
        this._shadowRoot.innerHTML = `<div class="wrapper">
        <a href="download/File.pdf" download>
            <button id="download">Download File</button>
        </a>
        <p>Link para download</p>
      </div>`;
    }
});

И мой HTML-файл, который использует его:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}
<script src='~/js/componente.js'></script>

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <x-element id='comp'></x-element>
</div>

Я загружаю свое расширение в Chrome и запускаю страницу.Я получаю журнал консоли Test, но метод attachShadow никогда не вызывается, и я все еще не могу получить доступ к закрытой тени DOM

Console log

Я был бы очень признателен за некоторыепомогите, что я делаю не так.Большое спасибо.

ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ

После внесения изменений в ответ мне нужно внести некоторые изменения в manifest.json.Ниже приведена окончательная версия:

{
    "name": "SeleniumTesting",
    "description": "Extension to open closed Shadow DOM for selenium testing",
    "version": "1",
    "author": "SeleniumTesting",
    "manifest_version": 2,
    "permissions": ["downloads", "<all_urls>"],
    "content_scripts": [{
        "matches": ["http://localhost:5000/*"],
        "run_at": "document_start",
        "all_frames": true,
        "js": ["shadowInject.js"]
    }],
    "web_accessible_resources": ["injected.js"]
}

Теперь это сработало, и Shadow DOM изменилось на открытое enter image description here

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

Как уже упоминалось в ответе Black-Hole, у скриптов контента есть свои собственные версии объектов DOM, поэтому вам придется добавить дополнительный скрипт для запуска в реальном DOM.

Если вы хотите коснутьсястраницы как можно меньше и держать тени закрытыми для остальной части страницы, вы можете использовать этот скрипт:

{
  const shadows = new WeakMap();
  const original = Element.prototype.attachShadow;
  Element.prototype.attachShadow = function() {
    const shadow = original.apply(this, arguments);
    shadows.set(this, shadow);
    return shadow;
  };

  // Later...
  shadows.get(document.querySelector("x-element"));
}
0 голосов
/ 02 марта 2019

Вы не должны помещать код в content_scripts, потому что content_scripts не совпадает с текущим контекстом страницы.

Вы пытаетесь изменить код shadowInject.js на:

const injectedScript = document.createElement('script');
injectedScript.src = chrome.extension.getURL('injected.js');
(document.head || document.documentElement).appendChild(injectedScript);

Тогдасоздайте файл injected.js в том же каталоге:

Содержимое файла:

console.log('test');
Element.prototype._attachShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = function () {
    console.log('attachShadow');
    return this._attachShadow( { mode: "open" } );
};

Вы можете попробовать его.Если есть какие-либо проблемы, пожалуйста, дайте мне знать

...