0

Background.js:

chrome.tabs.executeScript(tab.id, 
{
    file: "exec_script.js"
}, function(res) {
    console.log(res);
});

exec_script.js:

var test = html2canvas(document.body, {
  allowTaint: false,
  letterRendering: true,
  logging: true
}).then(function (canvas) {
    var dataUrl = canvas.toDataURL();
    var bImage = dataUrl.replace('data:image/png;base64,', '');
});
test

As far as I know, the last statement in exec_script.js have to be passed to the callback as the result parameter. But it returns empty object.

But if I make as following in exec_script.js:

var test = "good";
test

It returns a value of the variable to the callback.

Also the tab is not focused.

  • _"But it returns empty object"_ Are you sure `res` is a plain object? What value are you expecting to be passed to callback? – guest271314 Jan 23 '17 at 07:44
  • I want to see "bImage" value in the callback. – sloker antonov Jan 23 '17 at 07:47
  • Have you tried to `return` `bImage` from `.then()` chained to `html2canvas` call, chaining `.then()` to `res` at callback? – guest271314 Jan 23 '17 at 07:50
  • Like this [link](https://jsfiddle.net/4nucrpa9/) ? Yes, I've tried. The problem is that the `chrome.tabs.executeScript` doesn't block the extension process until the code in the tab has finished. – sloker antonov Jan 23 '17 at 07:56
  • `test` does not reference `bImage` value. `test` is a `Promise`, `.then()` is used to get `Promise` value. – guest271314 Jan 23 '17 at 08:43
  • Like this [https://jsfiddle.net/twmaqt2u/](https://jsfiddle.net/twmaqt2u/) ? It doesn't work too. Returns an empty array. – sloker antonov Jan 23 '17 at 08:54
  • Have you tried chaining `.then()` to `test` http://jsfiddle.net/4nucrpa9/1 or `res` https://jsfiddle.net/4nucrpa9/2/? – guest271314 Jan 23 '17 at 09:11
  • The tab is not active. It sends nothing untill I select tab. – sloker antonov Jan 23 '17 at 11:32
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Makyen Jan 23 '17 at 17:28

1 Answers1

1

The result returned by chrome.tabs.executeScript is produced by the main body of the executed script, in other words it is the standard behavior of synchronous JavaScript.

In your case the synchronous part creates test object, schedules a Promise but doesn't execute it yet (a task/microtask is queued), puts the just initialized test object as the last statement so that it gets picked up by executeScript. Furthermore, since executeScript transfers only JSON-ifiable portion of objects, and test being a complex class object, an empty object is transferred. You can check it manually by inspecting console.log(JSON.stringify(test)) in the console.

To transfer the results of asynchronous code use messaging:

  • background.js

    chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
        console.log(sender.tab, msg);
        // do something
    });
    chrome.tabs.executeScript(tab.id, {file: "exec_script.js"});
    
  • exec_script.js

    var test = html2canvas(document.body, {
      allowTaint: false,
      letterRendering: true,
      logging: true
    }).then(function(canvas) {
        var dataUrl = canvas.toDataURL();
        var bImage = dataUrl.replace('data:image/png;base64,', '');
        chrome.runtime.sendMessage({dataUrl: dataUrl});
    });
    

N.B. only JSON-ifiable portion of objects is transferred via messaging.

wOxxOm
  • 65,848
  • 11
  • 132
  • 136