       # Firefox doesn't support createShadowRoot, so guard against its non-existance.
       # https://hacks.mozilla.org/2018/10/firefox-63-tricks-and-treats/ says
       # Firefox 63 has enabled Shadow DOM v1 by default
-      @shadowDOM = shadowWrapper.attachShadow?( mode: "open" ) ?
-        shadowWrapper.createShadowRoot?() ? shadowWrapper
+      if shadowWrapper.attachShadow
+        @shadowDOM = shadowWrapper.attachShadow(mode: "open")
+      else
+        @shadowArrwap = shadowWrapper
       @shadowDOM.appendChild styleSheet
       @shadowDOM.appendChild @iframeElement
       @toggleIframeElementClasses "vimiumUIComponentVisible", "vimiumUIComponentHidden"

class UIComponent
  iframeElement: null
  iframePort: null
  showing: false
  iframeFrameId: null
  options: null
  shadowDOM: null

  toggleIframeElementClasses: (removeClass, addClass) ->
    @iframeElement.classList.remove removeClass
    unless @iframeElement.classList.contains addClass
      @iframeElement.classList.add addClass

  constructor: (iframeUrl, className, @handleMessage) ->
    DomUtils.documentReady =>
      styleSheet = DomUtils.createElement "style"
      styleSheet.type = "text/css"

            { port1, port2 } = new MessageChannel
            @iframeElement.contentWindow.postMessage vimiumSecret, chrome.runtime.getURL(""), [ port2 ]
            port1.onmessage = (event) =>
              eventName = null
              if event
                eventName = (if event.data then event.data.name) || event.data
              switch eventName
                when "uiComponentIsReady"
                  # If any other frame receives the focus, then hide the UI component.
                  chrome.runtime.onMessage.addListener ({name, focusFrameId}) =>
                    if name == "frameFocused" and @options and @options.focus and
                        not [frameId, @iframeFrameId].includes(focusFrameId)
                      @hide false
                    false # We will not be calling sendResponse.
                  # If this frame receives the focus, then hide the UI component.
                  window.addEventListener "focus", (forTrusted (event) =>
                    if event.target == window and @options and @options.focus
                      @hide false
                    true # Continue propagating the event.
                  ), true
