// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Populated by constants from the browser.  Used only by this file.
var NetInfoSources = null;

/**
 * This class provides a "bridge" for communicating between the javascript and
 * the browser.
 */
var BrowserBridge = (function() {
  'use strict';

  /**
   * Delay in milliseconds between updates of certain browser information.
   */
  var POLL_INTERVAL_MS = 5000;

  /**
   * @constructor
   */
  function BrowserBridge() {
    assertFirstConstructorCall(BrowserBridge);

    // List of observers for various bits of browser state.
    this.connectionTestsObservers_ = [];
    this.hstsObservers_ = [];
    this.constantsObservers_ = [];
    this.crosONCFileParseObservers_ = [];
    this.storeDebugLogsObservers_ = [];
    this.setNetworkDebugModeObservers_ = [];
    // Unprocessed data received before the constants.  This serves to protect
    // against passing along data before having information on how to interpret
    // it.
    this.earlyReceivedData_ = [];

    this.pollableDataHelpers_ = {};

    // Add PollableDataHelpers for NetInfoSources, which retrieve information
    // directly from the network stack.
    this.addNetInfoPollableDataHelper(
        'proxySettings', 'onProxySettingsChanged');
    this.addNetInfoPollableDataHelper('badProxies', 'onBadProxiesChanged');
    this.addNetInfoPollableDataHelper(
        'hostResolverInfo', 'onHostResolverInfoChanged');
    this.addNetInfoPollableDataHelper(
        'socketPoolInfo', 'onSocketPoolInfoChanged');
    this.addNetInfoPollableDataHelper(
        'spdySessionInfo', 'onSpdySessionInfoChanged');
    this.addNetInfoPollableDataHelper('spdyStatus', 'onSpdyStatusChanged');
    this.addNetInfoPollableDataHelper(
        'altSvcMappings', 'onAltSvcMappingsChanged');
    this.addNetInfoPollableDataHelper('quicInfo', 'onQuicInfoChanged');
    this.addNetInfoPollableDataHelper('sdchInfo', 'onSdchInfoChanged');
    this.addNetInfoPollableDataHelper(
        'httpCacheInfo', 'onHttpCacheInfoChanged');

    // Add other PollableDataHelpers.
    this.pollableDataHelpers_.sessionNetworkStats = new PollableDataHelper(
        'onSessionNetworkStatsChanged',
        this.sendGetSessionNetworkStats.bind(this));
    this.pollableDataHelpers_.historicNetworkStats = new PollableDataHelper(
        'onHistoricNetworkStatsChanged',
        this.sendGetHistoricNetworkStats.bind(this));
    if (cr.isWindows) {
      this.pollableDataHelpers_.serviceProviders = new PollableDataHelper(
          'onServiceProvidersChanged', this.sendGetServiceProviders.bind(this));
    }
    this.pollableDataHelpers_.prerenderInfo = new PollableDataHelper(
        'onPrerenderInfoChanged', this.sendGetPrerenderInfo.bind(this));
    this.pollableDataHelpers_.extensionInfo = new PollableDataHelper(
        'onExtensionInfoChanged', this.sendGetExtensionInfo.bind(this));
    this.pollableDataHelpers_.dataReductionProxyInfo = new PollableDataHelper(
        'onDataReductionProxyInfoChanged',
        this.sendGetDataReductionProxyInfo.bind(this));

    // Setting this to true will cause messages from the browser to be ignored,
    // and no messages will be sent to the browser, either.  Intended for use
    // when viewing log files.
    this.disabled_ = false;

    // Interval id returned by window.setInterval for polling timer.
    this.pollIntervalId_ = null;
  }

  cr.addSingletonGetter(BrowserBridge);

  BrowserBridge.prototype = {

    //--------------------------------------------------------------------------
    // Messages sent to the browser
    //--------------------------------------------------------------------------

    /**
     * Wraps |chrome.send|.  Doesn't send anything when disabled.
     */
    send: function(value1, value2) {
      if (!this.disabled_) {
        if (arguments.length == 1) {
          chrome.send(value1);
        } else if (arguments.length == 2) {
          chrome.send(value1, value2);
        } else {
          throw 'Unsupported number of arguments.';
        }
      }
    },

    sendReady: function() {
      this.send('notifyReady');
      this.setPollInterval(POLL_INTERVAL_MS);
    },

    /**
     * Some of the data we are interested is not currently exposed as a
     * stream.  This starts polling those with active observers (visible
     * views) every |intervalMs|.  Subsequent calls override previous calls
     * to this function.  If |intervalMs| is 0, stops polling.
     */
    setPollInterval: function(intervalMs) {
      if (this.pollIntervalId_ !== null) {
        window.clearInterval(this.pollIntervalId_);
        this.pollIntervalId_ = null;
      }

      if (intervalMs > 0) {
        this.pollIntervalId_ = window.setInterval(
            this.checkForUpdatedInfo.bind(this, false), intervalMs);
      }
    },

    sendGetNetInfo: function(netInfoSource) {
      // If don't have constants yet, don't do anything yet.
      if (NetInfoSources)
        this.send('getNetInfo', [NetInfoSources[netInfoSource]]);
    },

    sendReloadProxySettings: function() {
      this.send('reloadProxySettings');
    },

    sendClearBadProxies: function() {
      this.send('clearBadProxies');
    },

    sendClearHostResolverCache: function() {
      this.send('clearHostResolverCache');
    },

    sendClearBrowserCache: function() {
      this.send('clearBrowserCache');
    },

    sendClearAllCache: function() {
      this.sendClearHostResolverCache();
      this.sendClearBrowserCache();
    },

    sendStartConnectionTests: function(url) {
      this.send('startConnectionTests', [url]);
    },

    sendHSTSQuery: function(domain) {
      this.send('hstsQuery', [domain]);
    },

    sendHSTSAdd: function(
        domain, sts_include_subdomains, pkp_include_subdomains, pins) {
      this.send(
          'hstsAdd',
          [domain, sts_include_subdomains, pkp_include_subdomains, pins]);
    },

    sendHSTSDelete: function(domain) {
      this.send('hstsDelete', [domain]);
    },

    sendGetSessionNetworkStats: function() {
      this.send('getSessionNetworkStats');
    },

    sendGetHistoricNetworkStats: function() {
      this.send('getHistoricNetworkStats');
    },

    sendCloseIdleSockets: function() {
      this.send('closeIdleSockets');
    },

    sendFlushSocketPools: function() {
      this.send('flushSocketPools');
    },

    sendGetServiceProviders: function() {
      this.send('getServiceProviders');
    },

    sendGetPrerenderInfo: function() {
      this.send('getPrerenderInfo');
    },

    sendGetExtensionInfo: function() {
      this.send('getExtensionInfo');
    },

    sendGetDataReductionProxyInfo: function() {
      this.send('getDataReductionProxyInfo');
    },

    setCaptureMode: function(captureMode) {
      this.send('setCaptureMode', ['' + captureMode]);
    },

    importONCFile: function(fileContent, passcode) {
      this.send('importONCFile', [fileContent, passcode]);
    },

    storeDebugLogs: function() {
      this.send('storeDebugLogs');
    },

    setNetworkDebugMode: function(subsystem) {
      this.send('setNetworkDebugMode', [subsystem]);
    },

    //--------------------------------------------------------------------------
    // Messages received from the browser.
    //--------------------------------------------------------------------------

    receive: function(command, params) {
      // Does nothing if disabled.
      if (this.disabled_)
        return;

      // If no constants have been received, and params does not contain the
      // constants, delay handling the data.
      if (Constants == null && command != 'receivedConstants') {
        this.earlyReceivedData_.push({command: command, params: params});
        return;
      }

      this[command](params);

      // Handle any data that was received early in the order it was received,
      // once the constants have been processed.
      if (this.earlyReceivedData_ != null) {
        for (var i = 0; i < this.earlyReceivedData_.length; i++) {
          var command = this.earlyReceivedData_[i];
          this[command.command](command.params);
        }
        this.earlyReceivedData_ = null;
      }
    },

    receivedConstants: function(constants) {
      NetInfoSources = constants.netInfoSources;
      for (var i = 0; i < this.constantsObservers_.length; i++)
        this.constantsObservers_[i].onReceivedConstants(constants);
      // May have been waiting for the constants to be received before getting
      // information for the currently displayed tab.
      this.checkForUpdatedInfo();
    },

    receivedLogEntries: function(logEntries) {
      EventsTracker.getInstance().addLogEntries(logEntries);
    },

    receivedNetInfo: function(netInfo) {
      // Dispatch |netInfo| to the various PollableDataHelpers listening to
      // each field it contains.
      //
      // Currently information is only received from one source at a time, but
      // the API does allow for data from more that one to be requested at once.
      for (var source in netInfo)
        this.pollableDataHelpers_[source].update(netInfo[source]);
    },

    receivedSessionNetworkStats: function(sessionNetworkStats) {
      this.pollableDataHelpers_.sessionNetworkStats.update(sessionNetworkStats);
    },

    receivedHistoricNetworkStats: function(historicNetworkStats) {
      this.pollableDataHelpers_.historicNetworkStats.update(
          historicNetworkStats);
    },

    receivedServiceProviders: function(serviceProviders) {
      this.pollableDataHelpers_.serviceProviders.update(serviceProviders);
    },

    receivedStartConnectionTestSuite: function() {
      for (var i = 0; i < this.connectionTestsObservers_.length; i++)
        this.connectionTestsObservers_[i].onStartedConnectionTestSuite();
    },

    receivedStartConnectionTestExperiment: function(experiment) {
      for (var i = 0; i < this.connectionTestsObservers_.length; i++) {
        this.connectionTestsObservers_[i].onStartedConnectionTestExperiment(
            experiment);
      }
    },

    receivedCompletedConnectionTestExperiment: function(info) {
      for (var i = 0; i < this.connectionTestsObservers_.length; i++) {
        this.connectionTestsObservers_[i].onCompletedConnectionTestExperiment(
            info.experiment, info.result);
      }
    },

    receivedCompletedConnectionTestSuite: function() {
      for (var i = 0; i < this.connectionTestsObservers_.length; i++)
        this.connectionTestsObservers_[i].onCompletedConnectionTestSuite();
    },

    receivedHSTSResult: function(info) {
      for (var i = 0; i < this.hstsObservers_.length; i++)
        this.hstsObservers_[i].onHSTSQueryResult(info);
    },

    receivedONCFileParse: function(error) {
      for (var i = 0; i < this.crosONCFileParseObservers_.length; i++)
        this.crosONCFileParseObservers_[i].onONCFileParse(error);
    },

    receivedStoreDebugLogs: function(status) {
      for (var i = 0; i < this.storeDebugLogsObservers_.length; i++)
        this.storeDebugLogsObservers_[i].onStoreDebugLogs(status);
    },

    receivedSetNetworkDebugMode: function(status) {
      for (var i = 0; i < this.setNetworkDebugModeObservers_.length; i++)
        this.setNetworkDebugModeObservers_[i].onSetNetworkDebugMode(status);
    },

    receivedPrerenderInfo: function(prerenderInfo) {
      this.pollableDataHelpers_.prerenderInfo.update(prerenderInfo);
    },

    receivedExtensionInfo: function(extensionInfo) {
      this.pollableDataHelpers_.extensionInfo.update(extensionInfo);
    },

    receivedDataReductionProxyInfo: function(dataReductionProxyInfo) {
      this.pollableDataHelpers_.dataReductionProxyInfo.update(
          dataReductionProxyInfo);
    },

    //--------------------------------------------------------------------------

    /**
     * Prevents receiving/sending events to/from the browser.
     */
    disable: function() {
      this.disabled_ = true;
      this.setPollInterval(0);
    },

    /**
     * Returns true if the BrowserBridge has been disabled.
     */
    isDisabled: function() {
      return this.disabled_;
    },

    /**
     * Adds a listener of the proxy settings. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onProxySettingsChanged(proxySettings)
     *
     * |proxySettings| is a dictionary with (up to) two properties:
     *
     *   "original"  -- The settings that chrome was configured to use
     *                  (i.e. system settings.)
     *   "effective" -- The "effective" proxy settings that chrome is using.
     *                  (decides between the manual/automatic modes of the
     *                  fetched settings).
     *
     * Each of these two configurations is formatted as a string, and may be
     * omitted if not yet initialized.
     *
     * If |ignoreWhenUnchanged| is true, data is only sent when it changes.
     * If it's false, data is sent whenever it's received from the browser.
     */
    addProxySettingsObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.proxySettings.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the proxy settings. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onBadProxiesChanged(badProxies)
     *
     * |badProxies| is an array, where each entry has the property:
     *   badProxies[i].proxy_uri: String identify the proxy.
     *   badProxies[i].bad_until: The time when the proxy stops being considered
     *                            bad. Note the time is in time ticks.
     */
    addBadProxiesObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.badProxies.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the host resolver info. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onHostResolverInfoChanged(hostResolverInfo)
     */
    addHostResolverInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.hostResolverInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the socket pool. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onSocketPoolInfoChanged(socketPoolInfo)
     */
    addSocketPoolInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.socketPoolInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the network session. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onSessionNetworkStatsChanged(sessionNetworkStats)
     */
    addSessionNetworkStatsObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.sessionNetworkStats.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of persistent network session data. |observer| will be
     * called back when data is received, through:
     *
     *   observer.onHistoricNetworkStatsChanged(historicNetworkStats)
     */
    addHistoricNetworkStatsObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.historicNetworkStats.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the QUIC info. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onQuicInfoChanged(quicInfo)
     */
    addQuicInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.quicInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the SPDY info. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onSpdySessionInfoChanged(spdySessionInfo)
     */
    addSpdySessionInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.spdySessionInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the SPDY status. |observer| will be called back
     * when data is received, through:
     *
     *   observer.onSpdyStatusChanged(spdyStatus)
     */
    addSpdyStatusObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.spdyStatus.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the altSvcMappings. |observer| will be
     * called back when data is received, through:
     *
     *   observer.onAltSvcMappingsChanged(altSvcMappings)
     */
    addAltSvcMappingsObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.altSvcMappings.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the service providers info. |observer| will be called
     * back when data is received, through:
     *
     *   observer.onServiceProvidersChanged(serviceProviders)
     *
     * Will do nothing if on a platform other than Windows, as service providers
     * are only present on Windows.
     */
    addServiceProvidersObserver: function(observer, ignoreWhenUnchanged) {
      if (this.pollableDataHelpers_.serviceProviders) {
        this.pollableDataHelpers_.serviceProviders.addObserver(
            observer, ignoreWhenUnchanged);
      }
    },

    /**
     * Adds a listener for the progress of the connection tests.
     * The observer will be called back with:
     *
     *   observer.onStartedConnectionTestSuite();
     *   observer.onStartedConnectionTestExperiment(experiment);
     *   observer.onCompletedConnectionTestExperiment(experiment, result);
     *   observer.onCompletedConnectionTestSuite();
     */
    addConnectionTestsObserver: function(observer) {
      this.connectionTestsObservers_.push(observer);
    },

    /**
     * Adds a listener for the http cache info results.
     * The observer will be called back with:
     *
     *   observer.onHttpCacheInfoChanged(info);
     */
    addHttpCacheInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.httpCacheInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener for the results of HSTS (HTTPS Strict Transport Security)
     * queries. The observer will be called back with:
     *
     *   observer.onHSTSQueryResult(result);
     */
    addHSTSObserver: function(observer) {
      this.hstsObservers_.push(observer);
    },

    /**
     * Adds a listener for ONC file parse status. The observer will be called
     * back with:
     *
     *   observer.onONCFileParse(error);
     */
    addCrosONCFileParseObserver: function(observer) {
      this.crosONCFileParseObservers_.push(observer);
    },

    /**
     * Adds a listener for storing log file status. The observer will be called
     * back with:
     *
     *   observer.onStoreDebugLogs(status);
     */
    addStoreDebugLogsObserver: function(observer) {
      this.storeDebugLogsObservers_.push(observer);
    },

    /**
     * Adds a listener for network debugging mode status. The observer
     * will be called back with:
     *
     *   observer.onSetNetworkDebugMode(status);
     */
    addSetNetworkDebugModeObserver: function(observer) {
      this.setNetworkDebugModeObservers_.push(observer);
    },

    /**
     * Adds a listener for the received constants event. |observer| will be
     * called back when the constants are received, through:
     *
     *   observer.onReceivedConstants(constants);
     */
    addConstantsObserver: function(observer) {
      this.constantsObservers_.push(observer);
    },

    /**
     * Adds a listener for updated prerender info events
     * |observer| will be called back with:
     *
     *   observer.onPrerenderInfoChanged(prerenderInfo);
     */
    addPrerenderInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.prerenderInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of extension information. |observer| will be called
     * back when data is received, through:
     *
     *   observer.onExtensionInfoChanged(extensionInfo)
     */
    addExtensionInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.extensionInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of the data reduction proxy info. |observer| will be
     * called back when data is received, through:
     *
     *   observer.onDataReductionProxyInfoChanged(dataReductionProxyInfo)
     */
    addDataReductionProxyInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.dataReductionProxyInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * Adds a listener of SDCH information. |observer| will be called
     * back when data is received, through:
     *
     *   observer.onSdchInfoChanged(sdchInfo)
     */
    addSdchInfoObserver: function(observer, ignoreWhenUnchanged) {
      this.pollableDataHelpers_.sdchInfo.addObserver(
          observer, ignoreWhenUnchanged);
    },

    /**
     * If |force| is true, calls all startUpdate functions.  Otherwise, just
     * runs updates with active observers.
     */
    checkForUpdatedInfo: function(force) {
      for (var name in this.pollableDataHelpers_) {
        var helper = this.pollableDataHelpers_[name];
        if (force || helper.hasActiveObserver())
          helper.startUpdate();
      }
    },

    /**
     * Calls all startUpdate functions and, if |callback| is non-null,
     * calls it with the results of all updates.
     */
    updateAllInfo: function(callback) {
      if (callback)
        new UpdateAllObserver(callback, this.pollableDataHelpers_);
      this.checkForUpdatedInfo(true);
    },

    /**
     * Adds a PollableDataHelper that listens to the specified NetInfoSource.
     */
    addNetInfoPollableDataHelper: function(sourceName, observerMethodName) {
      this.pollableDataHelpers_[sourceName] = new PollableDataHelper(
          observerMethodName, this.sendGetNetInfo.bind(this, sourceName));
    },
  };

  /**
   * This is a helper class used by BrowserBridge, to keep track of:
   *   - the list of observers interested in some piece of data.
   *   - the last known value of that piece of data.
   *   - the name of the callback method to invoke on observers.
   *   - the update function.
   * @constructor
   */
  function PollableDataHelper(observerMethodName, startUpdateFunction) {
    this.observerMethodName_ = observerMethodName;
    this.startUpdate = startUpdateFunction;
    this.observerInfos_ = [];
  }

  PollableDataHelper.prototype = {
    getObserverMethodName: function() {
      return this.observerMethodName_;
    },

    isObserver: function(object) {
      for (var i = 0; i < this.observerInfos_.length; i++) {
        if (this.observerInfos_[i].observer === object)
          return true;
      }
      return false;
    },

    /**
     * If |ignoreWhenUnchanged| is true, we won't send data again until it
     * changes.
     */
    addObserver: function(observer, ignoreWhenUnchanged) {
      this.observerInfos_.push(new ObserverInfo(observer, ignoreWhenUnchanged));
    },

    removeObserver: function(observer) {
      for (var i = 0; i < this.observerInfos_.length; i++) {
        if (this.observerInfos_[i].observer === observer) {
          this.observerInfos_.splice(i, 1);
          return;
        }
      }
    },

    /**
     * Helper function to handle calling all the observers, but ONLY if the data
     * has actually changed since last time or the observer has yet to receive
     * any data. This is used for data we received from browser on an update
     * loop.
     */
    update: function(data) {
      var prevData = this.currentData_;
      var changed = false;

      // If the data hasn't changed since last time, will only need to notify
      // observers that have not yet received any data.
      if (!prevData || JSON.stringify(prevData) != JSON.stringify(data)) {
        changed = true;
        this.currentData_ = data;
      }

      // Notify the observers of the change, as needed.
      for (var i = 0; i < this.observerInfos_.length; i++) {
        var observerInfo = this.observerInfos_[i];
        if (changed || !observerInfo.hasReceivedData ||
            !observerInfo.ignoreWhenUnchanged) {
          observerInfo.observer[this.observerMethodName_](this.currentData_);
          observerInfo.hasReceivedData = true;
        }
      }
    },

    /**
     * Returns true if one of the observers actively wants the data
     * (i.e. is visible).
     */
    hasActiveObserver: function() {
      for (var i = 0; i < this.observerInfos_.length; i++) {
        if (this.observerInfos_[i].observer.isActive())
          return true;
      }
      return false;
    }
  };

  /**
   * This is a helper class used by PollableDataHelper, to keep track of
   * each observer and whether or not it has received any data.  The
   * latter is used to make sure that new observers get sent data on the
   * update following their creation.
   * @constructor
   */
  function ObserverInfo(observer, ignoreWhenUnchanged) {
    this.observer = observer;
    this.hasReceivedData = false;
    this.ignoreWhenUnchanged = ignoreWhenUnchanged;
  }

  /**
   * This is a helper class used by BrowserBridge to send data to
   * a callback once data from all polls has been received.
   *
   * It works by keeping track of how many polling functions have
   * yet to receive data, and recording the data as it it received.
   *
   * @constructor
   */
  function UpdateAllObserver(callback, pollableDataHelpers) {
    this.callback_ = callback;
    this.observingCount_ = 0;
    this.updatedData_ = {};

    for (var name in pollableDataHelpers) {
      ++this.observingCount_;
      var helper = pollableDataHelpers[name];
      helper.addObserver(this);
      this[helper.getObserverMethodName()] =
          this.onDataReceived_.bind(this, helper, name);
    }
  }

  UpdateAllObserver.prototype = {
    isActive: function() {
      return true;
    },

    onDataReceived_: function(helper, name, data) {
      helper.removeObserver(this);
      --this.observingCount_;
      this.updatedData_[name] = data;
      if (this.observingCount_ == 0)
        this.callback_(this.updatedData_);
    }
  };

  return BrowserBridge;
})();
