4

right now I'm developing a Chrome extension with Google's Dart. All works fine, except the onMessage-handling.

Chrome-Package used: API Ref. ~ OnMessageEvent Ref.

In the background-script i'm calling:

import 'package:chrome/chrome_ext.dart' as chrome;


void main() {
  //...
  //Binde event-listeners
  chrome.runtime.onMessage.listen(onMessage);
  //...
}

/**
 * Message event handling
 */
bool onMessage(chrome.OnMessageEvent messageEvent){

  JsObject message = messageEvent.message;
  JsFunction response = messageEvent.sendResponse;

  switch(message['action']){

    //...

    //Used by popup
    case 'refresh':
      print('Refresh called!');
      chrome.storage.sync.get().then((_){
        new JsObject(response, [new JsObject.jsify({'done': true})]);
      });

      //Idicate to send a response asynchronously (So it's said in the OnMessageEvent Ref.)
      return true;

    //...
  }

  return false;
}

My popup-scripts looks like this:

//...
chrome.runtime.sendMessage({
  'action': "refresh"
}).then((_){
  print('receiving response!');
});
//...

What is working: The message 'refresh' send from popup-script to background-script works! The background-script prints Refresh called!

What is not working: The popup-script never receives the response called from the background-script: new JsObject(response, [new JsObject.jsify({'done': true})]);.

I don't know how to handel sendResponse to really send an response. Maybe my call with JsObject is wrong? Hope someone else can help. (Btw. also a non async-response doesn't work here)


This problem is also open on github.com/dart-gde/chrome.dart.

Andi
  • 224
  • 2
  • 10

1 Answers1

3

Your problem might be in a way how you try to send the response back:

new JsObject(response, [new JsObject.jsify({'done': true})]);

According to the dart.js docs, the function should in your case be invoked like:

response.apply([new JsObject.jsify({'done': true})]);

Update: here the working code:

background.dart

import 'dart:js';

void main() {
  print("main()...");
  context['chrome']['runtime']['onMessage'].callMethod('addListener', [onMessageListener]);
}

void onMessageListener(request, sender, sendResponse) {
  print("received action = ${request['action']}");
  sendResponse.apply([new JsObject.jsify({'done': true})]);
}

popup.dart

import 'dart:js';

void main() {
  print("main():...");
  context['chrome']['runtime'].callMethod('sendMessage', [new JsObject.jsify({'action': 'refresh'}), (response) => print("received ${response['done']}")]);
}

Update: required patch to make it working in JavaScript too

As mentioned in comments, there is a problem with the returned object from context['chrome']['runtime']['onMessage'] ... If it is not JsObject it should be wrapped into it by using new JsObject.fromBrowserObject()

var jsObject = context['chrome']['runtime']['onMessage'];
(jsObject is JsObject ? jsObject : new JsObject.fromBrowserObject(jsObject))
.callMethod('addListener', [onMessageListener]);

Hope it helps ;-)

Community
  • 1
  • 1
Draško Kokić
  • 1,280
  • 1
  • 19
  • 34
  • As zoechi already mentioned on [github](https://github.com/dart-gde/chrome.dart/issues/150#issuecomment-36453868): "I tried response.apply([new JsObject.jsify({'done': true})]); This doesn't lead to an exception but the provided JavaScript callback doesn't get called either." – Andi Mar 02 '14 at 14:21
  • I updated the answer with the working dart code. I am using the straight dart:js in favour of dart:chrome package – Draško Kokić Mar 02 '14 at 15:07
  • Works for me as well! Thx. Btw. also an async response works when returning true in the eventListener. – Andi Mar 02 '14 at 17:00
  • Is this working now? I got a error when calling addListener. "context['chrome']['runtime']['onMessage'].callMethod('addListener', [onMessageListener]);" "Uncaught TypeError: J.p(...).a0 is not a function" My environments, - Version 47.0.2526.73 (64-bit) - Dart VM version: 1.13.0 (Wed Nov 18 12:15:29 2015) on "macos_x64" – ENDOH takanao Dec 05 '15 at 03:59
  • I got a error when calling addListener without dart2js minify. This line: "context['chrome']['runtime']['onMessage'].callMethod('addListener', [onMessageListener]);" A error: "Uncaught TypeError: J.$index$asx(...).callMethod$2 is not a function" – ENDOH takanao Dec 05 '15 at 04:16
  • I got a new solution. http://stackoverflow.com/questions/25631383/dart-chrome-extension-listen-to-chrome-api-events – ENDOH takanao Dec 05 '15 at 07:08
  • Thx @ENDOHtakanao ... I also came across this problem on another project ... pity it is still unresolved in `datr2js` after more then a year reporting it. – Draško Kokić Dec 06 '15 at 10:38