Question

The crossrider sidepanel is simply an iframe (you can use js-injected html, but I'm interested in using an iframe to reduce interference with the rest of the page). I'm having trouble getting any interaction between my browser extension and the iframe at all.

I see no point at all in adding a sidepanel with an extension unless you can do some basic JS communication. In this case I want a few options, checkboxes etc, in the iframe which control the extension. Since this plugin exists, I'm assuming there must be a way.

Ideally I'd like to have some basic input handling js in the child iframe and have it send back the odd save/load command. Is the answer really some form of message passing? If so which API should I be using here?

I believe this is related: Accessing iframe from chrome extension

[EDIT]
OK, so I've tried a few things...

  1. It seems the expected usage is to host the iframe's html content somewhere. A bit strange considering it should be local and part of the extension. What happens if you want to view some pages offline?? This is just silly and I'm dismissing it as an option. Why waste resources hosting something that should just be available locally.

  2. The alternative is to provide the HTML that goes in the sidebar. Note that this HTML doesn't get put in an iframe. I like the idea of an iframe because it keeps the CSS and JS very separate, so there's minimal interference between a page and your extension.

    So I tried creating an iframe via the html sidebar attribute with and ID and injected the content after a 100ms delay using myiframe.contentWindow.document.open/writeln/close(). This works fine on chrome but fails in firefox with a security error (The operation is insecure on open()).

  3. Another way is to provide the iframe content via the src url (for the sidebar I use a data address for the url attribute): Html code as IFRAME source rather than a URL. This works in firefox but results in a CORS error in chrome: The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "data". Protocols must match. and Warning: Blocked a frame with origin "http://localhost" from accessing a cross-origin frame. Function-name: appAPI.message.addListener

These CORS issues strike me as really daft. It's all my code coming from the same extension, injected into the same page. There's no cross origin happening, I created the damn thing. If I have the power to change the origin, then it's not secure in the first place so why bother.

Was it helpful?

Solution

Assuming you are using the url sidebar property to load your sidebar's HTML (i.e. a hosted web page), you can use the extension's Run in Iframe feature to communicate between the iframe extension and the parent window's extension.

To achieve this, first enable the extension to run in iframes (Settings > Run in Iframes) and then you can use the extension.js to load your sidebar and handle messaging. For example, the following code loads a page that has a button with identification btnSave:

Hosted web page file:

<html>
<head>
</head>
<body>
  <div id="mySidebar">
    My sidebar form
    <br />
    <button id="btnSave">Save</button>
  </div>
</body>
</html>

extension.js file:

appAPI.ready(function($) {
  // Check if running in iframe and the sidebar page loaded
  if (appAPI.dom.isIframe() && $('#mySidebar').length) {
    // Set click handler for button to send message to parent window
    $('#btnSave').click(function() {
      appAPI.message.toCurrentTabWindow({
        type:'save',
        data:'My save data'
      });
    });
    // End of Iframe code ... exit
    return;
  }

  // Parent window message listener
  appAPI.message.addListener(function(msg) {
    if (msg.type === 'save') {
      console.log('Extn:: Parent received data: ' +
        appAPI.JSON.stringify(msg.data));
    }
  });

  // Create the sidebar
  var sidebar = new appAPI.sidebar({
    position:'right',
    url: 'http://yourdomain.com/sidebar_page.html',
     title:{
      content:'Sidebar Title',
      close:true
    },
    opacity:1.0,
    width:'300px',
    height:'650px',
    preloader:true,
    sticky:true,
    slide:150,
    openAction:['click', 'mouseover'],
    closeAction:'click',
    theme:'default',
    scrollbars:false,
    openOnInstall:true,
    events:{
      onShow:function () {
        console.log("Extn:: Show sidebar event triggered");
      },
      onHide:function () {
        console.log("Extn:: Hide sidebar event triggered");
      }
    }
  });
});

However, if you are using the html sidebar property to load your sidebar's HTML, then this solution will not work since the extension does not run in this context. However, you may be able to utilize the methods described in the StackOverflow thread you quoted to communicate with the parent window (this would be browser specific) that in turn can communicate with the extension using our CrossriderAPI event.

[Disclaimer: I am a Crossrider employee]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top