1

it's days I'm trying to figure out how to make a chrome extension I'm building working...with AngularJS. Problem is that I cannot successfully access remote resources; as long as I didn't use angular, my way to communicate between the main html and the sandbox was with a pub/sub javascript I found on the web pkg.js and in this way I could call external urls in the main.js and pass retrieved data back to subscribed javascripts.

I have heavily simplified my code so that you can better understand the architecture. Here are some test resources that works perfectly apart from the fact...that angular does not work :/

My manifest has the following relevant parts:

{
...
"background": {
 "scripts": ["new/ext/background.js"],
 "persistent": false
},
"permissions": [
 "tabs",
 "http://*.mysite.com/*"
],
"sandbox": {
 "pages": [ "new/testmain.html" ]
},
"content_security_policy": "script-src 'self' https://ajax.googleapis.com; object-src 'self'"
}

My background.js is very simple: it just creates a tab and calls an html which will host the angular code:

chrome.browserAction.onClicked.addListener(function (tab) {
  chrome.tabs.create({'url': chrome.extension.getURL('/new/main.html')}, function (tab) {     });
});

The main.html is, too, pretty easy: just some script includes and the iframe:

<!doctype html>
<html>
<head>
  <title>Testing angular</title>

  <script type='text/javascript' src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>

  <!-- custom scripts -->
  <script type="text/javascript" src="/lib/pkg.js"></script>

</head>
  <body style="height: 100%">
  <h1>Iframe below</h1>
  <iframe id="iframe" src="testmain.html" width="100%" height="100%" frameborder="none"></iframe>

  <script type="text/javascript" src="testmain.js"></script>

</body>
</html>

The testmain.js just subscribes to an event and, in case receives it, it publishes dummy data:

iframe = document.getElementById("iframe");
$.pkg.init(iframe.contentWindow);

$.pkg.listen("items", function () {
  console.log("[testmain.js] received items message");
  items = [
      { name:"foo", age: 12 },
      { name:"bar", age: 11 },
      { name:"mickey", age: 15},
      { name: "donald", age: 27}
  ];
  $.pkg.send("response", [items]);
  console.log("[testmain.js] sent response");
});

Now let's come to testmain.html:

<!DOCTYPE html>
<html data-ng-app="App" data-ng-csp>
<head>
  <title></title>
</head>
<body ng-controller="TodoCtrl">
  <div ng-repeat="item in testitems">
    <ul>
      <li>{{item.name}}</li>
    </ul>
  </div>
  <script type='text/javascript' src="lib/jquery.min.js"></script>
  <script type="text/javascript" src="lib/angular.min.js"></script>
  <script src="/lib/pkg.js"></script>
  <script src="app/testapp.js"></script>
</body>
</html>

And, finally, here is the testapp.js:

var App = angular.module('App', []);

App.controller('TodoCtrl', function($scope) {

  //test
  $.pkg.init(window.top);
  $.pkg.send("items");
  console.log("[testapp.js] sent message items");
  $.pkg.listen("response", function(res){
    console.log("[testapp.js] received " + res.length + " items");
    $scope.testitems = res;
    for (i = 0; i < $scope.testitems.length; i++) {
       console.log("[testapp.js] testitem: " + $scope.testitems[i].name);
    }
  });
});

The controller just inits the communication with destination = html containing the iframe. It then sends a message requesting for data which is then sent back (listens).

If I try from the console to run any manual command to get the $scope variable, no success at all:

document.getElementById('iframe')
Sandbox access violation: Blocked a frame at "chrome-extension://jcnppfndabbcgbdcnjncnoddmhmkmmbb" from accessing a frame at "chrome-extension://jcnppfndabbcgbdcnjncnoddmhmkmmbb".  The frame being accessed is sandboxed and lacks the "allow-same-origin" flag.
Sandbox access violation: Blocked a frame at "chrome-extension://jcnppfndabbcgbdcnjncnoddmhmkmmbb" from accessing a frame at "chrome-extension://jcnppfndabbcgbdcnjncnoddmhmkmmbb".  The frame being accessed is sandboxed and lacks the "allow-same-origin" flag.
Sandbox access violation: Blocked a frame at "chrome-extension://jcnppfndabbcgbdcnjncnoddmhmkmmbb" from accessing a frame at "chrome-extension://jcnppfndabbcgbdcnjncnoddmhmkmmbb".  The frame being accessed is sandboxed and lacks the "allow-same-origin" flag.
<iframe id="iframe" src="testmain.html" width="100%" height="100%" frameborder="none"></iframe>

This is what happens in the console:

[testapp.js] sent message items testapp.js:8
[testmain.js] received items message testmain.js:5
[testmain.js] sent response testmain.js:13
[testapp.js] received 4 items testapp.js:10
[testapp.js] testitem: pippo testapp.js:13
[testapp.js] testitem: pluto testapp.js:13
[testapp.js] testitem: paperino testapp.js:13
[testapp.js] testitem: minnie testapp.js:13

as you may notice, communication DO occur, $scope.testitems variable is set correctly. BUT nothing is rendered on the iframe :(

Can anyone help me figure out how to come out of all of this?

Btw, I was in a some way forced to do so - the first version which was on plnkr gladly used the $http inside the controller, but this appears to be prohibited in chrome extensions... I also tried to use amplifyjs but didn't come to out to make the communication work between an iframe and its container.

Thanks a lot!

  • Have you read [this](http://stackoverflow.com/questions/17634751/sandbox-access-violation-when-using-tinyeditor-wysiwyg-editor-in-chrome-extensio)? Why use an iframe in the first place? Also, `$http` should work fine in extensions in general (I use it). – hiattp Nov 03 '13 at 14:33
  • I read that, but didn't find any help. It was the same error I got before putting ng-scp tag. Can you explain me how $http can work in a controller called in an html that represents your extension? I would be really glad to remove this sandbox complication... In addition, I tried the same example but statically setting with variable $scope.testitems = [ { name: "bla", "age": 1 } ] in testapp.js...and the ng-repeat just worked without any problem. – Giu e Mik Foto Nov 03 '13 at 15:54
  • You have a lot going on here, I recommend breaking this up or simplifying your question. If you don't have a compelling reason to use an iframe get rid of it (hopefully moving you beyond this immediate problem), then if you run into trouble with `$http`, post another question. – hiattp Nov 04 '13 at 02:30
  • OK, I agree. Let's stick with the original question then: why doesn't ng-app render? – Giu e Mik Foto Nov 04 '13 at 10:30
  • Did you try adding `sandbox="allow-same-origin"` to your iframe in `main.html`? – hiattp Nov 04 '13 at 14:49
  • yes, it doesn't work. I think I've found a possible answer, see here [link](http://stackoverflow.com/questions/19705500/angularjs-why-i-need-to-click-on-a-button-to-get-my-view-updated) I will try later and see if this works...but what is not clear to me is the reason WHY... – Giu e Mik Foto Nov 04 '13 at 16:09
  • possible duplicate of [Angularjs: call other scope which in iframe](http://stackoverflow.com/questions/18437594/angularjs-call-other-scope-which-in-iframe) – Paul Sweatte Dec 22 '14 at 12:24

0 Answers0