Home | History | Annotate | Download | only in gaia_auth
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 /**
      6  * Channel to the background script.
      7  */
      8 function Channel() {
      9 }
     10 
     11 /** @const */
     12 Channel.INTERNAL_REQUEST_MESSAGE = 'internal-request-message';
     13 
     14 /** @const */
     15 Channel.INTERNAL_REPLY_MESSAGE = 'internal-reply-message';
     16 
     17 Channel.prototype = {
     18   // Message port to use to communicate with background script.
     19   port_: null,
     20 
     21   // Registered message callbacks.
     22   messageCallbacks_: {},
     23 
     24   // Internal request id to track pending requests.
     25   nextInternalRequestId_: 0,
     26 
     27   // Pending internal request callbacks.
     28   internalRequestCallbacks_: {},
     29 
     30   /**
     31    * Initialize the channel with given port for the background script.
     32    */
     33   init: function(port) {
     34     this.port_ = port;
     35     this.port_.onMessage.addListener(this.onMessage_.bind(this));
     36   },
     37 
     38   /**
     39    * Connects to the background script with the given name.
     40    */
     41   connect: function(name) {
     42     this.port_ = chrome.runtime.connect({name: name});
     43     this.port_.onMessage.addListener(this.onMessage_.bind(this));
     44   },
     45 
     46   /**
     47    * Associates a message name with a callback. When a message with the name
     48    * is received, the callback will be invoked with the message as its arg.
     49    * Note only the last registered callback will be invoked.
     50    */
     51   registerMessage: function(name, callback) {
     52     this.messageCallbacks_[name] = callback;
     53   },
     54 
     55   /**
     56    * Sends a message to the other side of the channel.
     57    */
     58   send: function(msg) {
     59     this.port_.postMessage(msg);
     60   },
     61 
     62   /**
     63    * Sends a message to the other side and invokes the callback with
     64    * the replied object. Useful for message that expects a returned result.
     65    */
     66   sendWithCallback: function(msg, callback) {
     67     var requestId = this.nextInternalRequestId_++;
     68     this.internalRequestCallbacks_[requestId] = callback;
     69     this.send({
     70       name: Channel.INTERNAL_REQUEST_MESSAGE,
     71       requestId: requestId,
     72       payload: msg
     73     });
     74   },
     75 
     76   /**
     77    * Invokes message callback using given message.
     78    * @return {*} The return value of the message callback or null.
     79    */
     80   invokeMessageCallbacks_: function(msg) {
     81     var name = msg.name;
     82     if (this.messageCallbacks_[name])
     83       return this.messageCallbacks_[name](msg);
     84 
     85     console.error('Error: Unexpected message, name=' + name);
     86     return null;
     87   },
     88 
     89   /**
     90    * Invoked when a message is received.
     91    */
     92   onMessage_: function(msg) {
     93     var name = msg.name;
     94     if (name == Channel.INTERNAL_REQUEST_MESSAGE) {
     95       var payload = msg.payload;
     96       var result = this.invokeMessageCallbacks_(payload);
     97       this.send({
     98         name: Channel.INTERNAL_REPLY_MESSAGE,
     99         requestId: msg.requestId,
    100         result: result
    101       });
    102     } else if (name == Channel.INTERNAL_REPLY_MESSAGE) {
    103       var callback = this.internalRequestCallbacks_[msg.requestId];
    104       delete this.internalRequestCallbacks_[msg.requestId];
    105       if (callback)
    106         callback(msg.result);
    107     } else {
    108       this.invokeMessageCallbacks_(msg);
    109     }
    110   }
    111 };
    112