browserpass / browserpass-extension

Browserpass web extension
ISC License
840 stars 51 forks source link

Need support for shadowDOM #73

Open intervalia opened 5 years ago

intervalia commented 5 years ago

General information

Your app does not support a form that exists in shadowDom and provides no way to let the app know that a form is held within the shadowDom of a particular element. As more Web Components are created there is a larger likelihood of this app not functioning since the <form> may be held within the shadowDOM of the Web Component. And, you can use shadowDOM without a Web Component. Several frameworks are not using shadowDOM for much of their DOM creation. We need some way to indicate that the login <form> is held inside the element's shadowDOM so the appropriate parent can be used for the call to querySelectorAll.

Exact steps to reproduce the problem

  1. Use a form contained in shadowDOM
  2. Try to use the app
  3. It does not work

What should happen?

There should be a way to indicate that the shadowDOM of a given element contains the login form.

What happened instead?

The app can not see the shadowDOM. document.querySelectorAll does not penetrate into shadowDOM and, thus, can not find a <form> that is contained in shadowDOM. There is no way to indicate that a particular element has a login <form> held within its shadowDOM.

erayd commented 5 years ago

@intervalia Thanks for raising this - I consider the lack of deep selection inside shadow roots to be a bug, and will work to add it.

maximbaz commented 5 years ago

Do you guys have an example page where this can be reproduced?

intervalia commented 5 years ago

I will send something later today.

On Thu, Feb 14, 2019, 14:50 Maxim Baz <notifications@github.com wrote:

Do you guys have an example page where this can be reproduced?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/browserpass/browserpass/issues/319#issuecomment-463813389, or mute the thread https://github.com/notifications/unsubscribe-auth/ABg64fgzKbBZZ6jx-uWDPpHKUkll_ljyks5vNdo9gaJpZM4a8crH .

intervalia commented 5 years ago

Sorry. I was in meeting until late. Here is some code that should work for your testing:

<!doctype html>
<html>
<head>
  <title>Form in shadowDOM example</title>
</head>
<body>
  <script>
  (function() {
    function getTemplate() {
      var templateEl = document.createElement('template');

      templateEl.innerHTML = `
      <style>
      :host, form{width:300px}
      label{display:block;}
      form input{display:block;margin-bottom:20px;padding: 4px 8px;width:100%;}
      button{padding: 4px 8px;}
      </style>
      <form id="login">
        <label for="username">Username:</label>
        <input type="text" id="username"/>
        <label for="password">Password:</label>
        <input type="password" id="password"/>
        <button class="btn btn-sm" id="signin">Login</button>
        <div class="error-message"></div>
      </form>`;

      return templateEl.content;
    }

    function performLogin(evt) {
      evt.preventDefault();
      evt.stopPropagation();

      const username = this.querySelector('#username').value;
      const password = this.querySelector('#password').value;

      console.log('Username', username);
      console.log('Password', password);
    }

    // Class for `<sd-login>`
    class LoginForm extends HTMLElement {
      constructor() {
        super();
        const shadow = this.attachShadow({mode:'open'});
        shadow.appendChild(getTemplate());

        const formEl = shadow.querySelector('form');
        formEl.addEventListener('submit', performLogin.bind(shadow));
      }

      connectedCallback() {
        this.shadowRoot.querySelector('input').focus();
      }
    }

    // Define our web component
    customElements.define('sd-login', LoginForm);
  })();
  </script>
  <sd-login></sd-login>
  <hr/>
  <p>It would be great if we could just add an attribute to the element &gt;sd-login&lt;
    that would let your system know where the form is located. But that would put the
    burden on every developer and every webpage that uses shadowDOM</p>
</body>
</html>