OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 // Populated by constants from the browser. Used only by this file. |
| 6 var NetInfoSources = null; |
| 7 |
| 8 /** |
| 9 * This class provides a "bridge" for communicating between the javascript and |
| 10 * the browser. |
| 11 */ |
| 12 var BrowserBridge = (function() { |
| 13 'use strict'; |
| 14 |
| 15 /** |
| 16 * Delay in milliseconds between updates of certain browser information. |
| 17 */ |
| 18 var POLL_INTERVAL_MS = 5000; |
| 19 |
| 20 /** |
| 21 * @constructor |
| 22 */ |
| 23 function BrowserBridge() { |
| 24 assertFirstConstructorCall(BrowserBridge); |
| 25 |
| 26 // List of observers for various bits of browser state. |
| 27 this.connectionTestsObservers_ = []; |
| 28 this.hstsObservers_ = []; |
| 29 this.constantsObservers_ = []; |
| 30 this.crosONCFileParseObservers_ = []; |
| 31 this.storeDebugLogsObservers_ = []; |
| 32 this.setNetworkDebugModeObservers_ = []; |
| 33 // Unprocessed data received before the constants. This serves to protect |
| 34 // against passing along data before having information on how to interpret |
| 35 // it. |
| 36 this.earlyReceivedData_ = []; |
| 37 |
| 38 this.pollableDataHelpers_ = {}; |
| 39 |
| 40 // Add PollableDataHelpers for NetInfoSources, which retrieve information |
| 41 // directly from the network stack. |
| 42 this.addNetInfoPollableDataHelper('proxySettings', |
| 43 'onProxySettingsChanged'); |
| 44 this.addNetInfoPollableDataHelper('badProxies', 'onBadProxiesChanged'); |
| 45 this.addNetInfoPollableDataHelper('hostResolverInfo', |
| 46 'onHostResolverInfoChanged'); |
| 47 this.addNetInfoPollableDataHelper('socketPoolInfo', |
| 48 'onSocketPoolInfoChanged'); |
| 49 this.addNetInfoPollableDataHelper('spdySessionInfo', |
| 50 'onSpdySessionInfoChanged'); |
| 51 this.addNetInfoPollableDataHelper('spdyStatus', 'onSpdyStatusChanged'); |
| 52 this.addNetInfoPollableDataHelper('altSvcMappings', |
| 53 'onAltSvcMappingsChanged'); |
| 54 this.addNetInfoPollableDataHelper('quicInfo', 'onQuicInfoChanged'); |
| 55 this.addNetInfoPollableDataHelper('sdchInfo', 'onSdchInfoChanged'); |
| 56 this.addNetInfoPollableDataHelper('httpCacheInfo', |
| 57 'onHttpCacheInfoChanged'); |
| 58 |
| 59 // Add other PollableDataHelpers. |
| 60 this.pollableDataHelpers_.sessionNetworkStats = |
| 61 new PollableDataHelper('onSessionNetworkStatsChanged', |
| 62 this.sendGetSessionNetworkStats.bind(this)); |
| 63 this.pollableDataHelpers_.historicNetworkStats = |
| 64 new PollableDataHelper('onHistoricNetworkStatsChanged', |
| 65 this.sendGetHistoricNetworkStats.bind(this)); |
| 66 if (cr.isWindows) { |
| 67 this.pollableDataHelpers_.serviceProviders = |
| 68 new PollableDataHelper('onServiceProvidersChanged', |
| 69 this.sendGetServiceProviders.bind(this)); |
| 70 } |
| 71 this.pollableDataHelpers_.prerenderInfo = |
| 72 new PollableDataHelper('onPrerenderInfoChanged', |
| 73 this.sendGetPrerenderInfo.bind(this)); |
| 74 this.pollableDataHelpers_.extensionInfo = |
| 75 new PollableDataHelper('onExtensionInfoChanged', |
| 76 this.sendGetExtensionInfo.bind(this)); |
| 77 this.pollableDataHelpers_.dataReductionProxyInfo = |
| 78 new PollableDataHelper('onDataReductionProxyInfoChanged', |
| 79 this.sendGetDataReductionProxyInfo.bind(this)); |
| 80 |
| 81 // Setting this to true will cause messages from the browser to be ignored, |
| 82 // and no messages will be sent to the browser, either. Intended for use |
| 83 // when viewing log files. |
| 84 this.disabled_ = false; |
| 85 |
| 86 // Interval id returned by window.setInterval for polling timer. |
| 87 this.pollIntervalId_ = null; |
| 88 } |
| 89 |
| 90 cr.addSingletonGetter(BrowserBridge); |
| 91 |
| 92 BrowserBridge.prototype = { |
| 93 |
| 94 //-------------------------------------------------------------------------- |
| 95 // Messages sent to the browser |
| 96 //-------------------------------------------------------------------------- |
| 97 |
| 98 /** |
| 99 * Wraps |chrome.send|. Doesn't send anything when disabled. |
| 100 */ |
| 101 send: function(value1, value2) { |
| 102 if (console && console.warn) { |
| 103 console.warn('TODO: Called deprecated BrowserBridge.send'); |
| 104 } |
| 105 return; |
| 106 |
| 107 /*if (!this.disabled_) { |
| 108 if (arguments.length == 1) { |
| 109 chrome.send(value1); |
| 110 } else if (arguments.length == 2) { |
| 111 chrome.send(value1, value2); |
| 112 } else { |
| 113 throw 'Unsupported number of arguments.'; |
| 114 } |
| 115 }*/ |
| 116 }, |
| 117 |
| 118 sendReady: function() { |
| 119 this.send('notifyReady'); |
| 120 this.setPollInterval(POLL_INTERVAL_MS); |
| 121 }, |
| 122 |
| 123 /** |
| 124 * Some of the data we are interested is not currently exposed as a |
| 125 * stream. This starts polling those with active observers (visible |
| 126 * views) every |intervalMs|. Subsequent calls override previous calls |
| 127 * to this function. If |intervalMs| is 0, stops polling. |
| 128 */ |
| 129 setPollInterval: function(intervalMs) { |
| 130 if (this.pollIntervalId_ !== null) { |
| 131 window.clearInterval(this.pollIntervalId_); |
| 132 this.pollIntervalId_ = null; |
| 133 } |
| 134 |
| 135 if (intervalMs > 0) { |
| 136 this.pollIntervalId_ = |
| 137 window.setInterval(this.checkForUpdatedInfo.bind(this, false), |
| 138 intervalMs); |
| 139 } |
| 140 }, |
| 141 |
| 142 sendGetNetInfo: function(netInfoSource) { |
| 143 // If don't have constants yet, don't do anything yet. |
| 144 if (NetInfoSources) |
| 145 this.send('getNetInfo', [NetInfoSources[netInfoSource]]); |
| 146 }, |
| 147 |
| 148 sendReloadProxySettings: function() { |
| 149 this.send('reloadProxySettings'); |
| 150 }, |
| 151 |
| 152 sendClearBadProxies: function() { |
| 153 this.send('clearBadProxies'); |
| 154 }, |
| 155 |
| 156 sendClearHostResolverCache: function() { |
| 157 this.send('clearHostResolverCache'); |
| 158 }, |
| 159 |
| 160 sendClearBrowserCache: function() { |
| 161 this.send('clearBrowserCache'); |
| 162 }, |
| 163 |
| 164 sendClearAllCache: function() { |
| 165 this.sendClearHostResolverCache(); |
| 166 this.sendClearBrowserCache(); |
| 167 }, |
| 168 |
| 169 sendStartConnectionTests: function(url) { |
| 170 this.send('startConnectionTests', [url]); |
| 171 }, |
| 172 |
| 173 sendHSTSQuery: function(domain) { |
| 174 this.send('hstsQuery', [domain]); |
| 175 }, |
| 176 |
| 177 sendHSTSAdd: function(domain, sts_include_subdomains, |
| 178 pkp_include_subdomains, pins) { |
| 179 this.send('hstsAdd', [domain, sts_include_subdomains, |
| 180 pkp_include_subdomains, pins]); |
| 181 }, |
| 182 |
| 183 sendHSTSDelete: function(domain) { |
| 184 this.send('hstsDelete', [domain]); |
| 185 }, |
| 186 |
| 187 sendGetSessionNetworkStats: function() { |
| 188 this.send('getSessionNetworkStats'); |
| 189 }, |
| 190 |
| 191 sendGetHistoricNetworkStats: function() { |
| 192 this.send('getHistoricNetworkStats'); |
| 193 }, |
| 194 |
| 195 sendCloseIdleSockets: function() { |
| 196 this.send('closeIdleSockets'); |
| 197 }, |
| 198 |
| 199 sendFlushSocketPools: function() { |
| 200 this.send('flushSocketPools'); |
| 201 }, |
| 202 |
| 203 sendGetServiceProviders: function() { |
| 204 this.send('getServiceProviders'); |
| 205 }, |
| 206 |
| 207 sendGetPrerenderInfo: function() { |
| 208 this.send('getPrerenderInfo'); |
| 209 }, |
| 210 |
| 211 sendGetExtensionInfo: function() { |
| 212 this.send('getExtensionInfo'); |
| 213 }, |
| 214 |
| 215 sendGetDataReductionProxyInfo: function() { |
| 216 this.send('getDataReductionProxyInfo'); |
| 217 }, |
| 218 |
| 219 setCaptureMode: function(captureMode) { |
| 220 this.send('setCaptureMode', ['' + captureMode]); |
| 221 }, |
| 222 |
| 223 importONCFile: function(fileContent, passcode) { |
| 224 this.send('importONCFile', [fileContent, passcode]); |
| 225 }, |
| 226 |
| 227 storeDebugLogs: function() { |
| 228 this.send('storeDebugLogs'); |
| 229 }, |
| 230 |
| 231 setNetworkDebugMode: function(subsystem) { |
| 232 this.send('setNetworkDebugMode', [subsystem]); |
| 233 }, |
| 234 |
| 235 //-------------------------------------------------------------------------- |
| 236 // Messages received from the browser. |
| 237 //-------------------------------------------------------------------------- |
| 238 |
| 239 receive: function(command, params) { |
| 240 // Does nothing if disabled. |
| 241 if (this.disabled_) |
| 242 return; |
| 243 |
| 244 // If no constants have been received, and params does not contain the |
| 245 // constants, delay handling the data. |
| 246 if (Constants == null && command != 'receivedConstants') { |
| 247 this.earlyReceivedData_.push({ command: command, params: params }); |
| 248 return; |
| 249 } |
| 250 |
| 251 this[command](params); |
| 252 |
| 253 // Handle any data that was received early in the order it was received, |
| 254 // once the constants have been processed. |
| 255 if (this.earlyReceivedData_ != null) { |
| 256 for (var i = 0; i < this.earlyReceivedData_.length; i++) { |
| 257 var command = this.earlyReceivedData_[i]; |
| 258 this[command.command](command.params); |
| 259 } |
| 260 this.earlyReceivedData_ = null; |
| 261 } |
| 262 }, |
| 263 |
| 264 receivedConstants: function(constants) { |
| 265 NetInfoSources = constants.netInfoSources; |
| 266 for (var i = 0; i < this.constantsObservers_.length; i++) |
| 267 this.constantsObservers_[i].onReceivedConstants(constants); |
| 268 // May have been waiting for the constants to be received before getting |
| 269 // information for the currently displayed tab. |
| 270 this.checkForUpdatedInfo(); |
| 271 }, |
| 272 |
| 273 receivedLogEntries: function(logEntries) { |
| 274 EventsTracker.getInstance().addLogEntries(logEntries); |
| 275 }, |
| 276 |
| 277 receivedNetInfo: function(netInfo) { |
| 278 // Dispatch |netInfo| to the various PollableDataHelpers listening to |
| 279 // each field it contains. |
| 280 // |
| 281 // Currently information is only received from one source at a time, but |
| 282 // the API does allow for data from more that one to be requested at once. |
| 283 for (var source in netInfo) |
| 284 this.pollableDataHelpers_[source].update(netInfo[source]); |
| 285 }, |
| 286 |
| 287 receivedSessionNetworkStats: function(sessionNetworkStats) { |
| 288 this.pollableDataHelpers_.sessionNetworkStats.update(sessionNetworkStats); |
| 289 }, |
| 290 |
| 291 receivedHistoricNetworkStats: function(historicNetworkStats) { |
| 292 this.pollableDataHelpers_.historicNetworkStats.update( |
| 293 historicNetworkStats); |
| 294 }, |
| 295 |
| 296 receivedServiceProviders: function(serviceProviders) { |
| 297 this.pollableDataHelpers_.serviceProviders.update(serviceProviders); |
| 298 }, |
| 299 |
| 300 receivedStartConnectionTestSuite: function() { |
| 301 for (var i = 0; i < this.connectionTestsObservers_.length; i++) |
| 302 this.connectionTestsObservers_[i].onStartedConnectionTestSuite(); |
| 303 }, |
| 304 |
| 305 receivedStartConnectionTestExperiment: function(experiment) { |
| 306 for (var i = 0; i < this.connectionTestsObservers_.length; i++) { |
| 307 this.connectionTestsObservers_[i].onStartedConnectionTestExperiment( |
| 308 experiment); |
| 309 } |
| 310 }, |
| 311 |
| 312 receivedCompletedConnectionTestExperiment: function(info) { |
| 313 for (var i = 0; i < this.connectionTestsObservers_.length; i++) { |
| 314 this.connectionTestsObservers_[i].onCompletedConnectionTestExperiment( |
| 315 info.experiment, info.result); |
| 316 } |
| 317 }, |
| 318 |
| 319 receivedCompletedConnectionTestSuite: function() { |
| 320 for (var i = 0; i < this.connectionTestsObservers_.length; i++) |
| 321 this.connectionTestsObservers_[i].onCompletedConnectionTestSuite(); |
| 322 }, |
| 323 |
| 324 receivedHSTSResult: function(info) { |
| 325 for (var i = 0; i < this.hstsObservers_.length; i++) |
| 326 this.hstsObservers_[i].onHSTSQueryResult(info); |
| 327 }, |
| 328 |
| 329 receivedONCFileParse: function(error) { |
| 330 for (var i = 0; i < this.crosONCFileParseObservers_.length; i++) |
| 331 this.crosONCFileParseObservers_[i].onONCFileParse(error); |
| 332 }, |
| 333 |
| 334 receivedStoreDebugLogs: function(status) { |
| 335 for (var i = 0; i < this.storeDebugLogsObservers_.length; i++) |
| 336 this.storeDebugLogsObservers_[i].onStoreDebugLogs(status); |
| 337 }, |
| 338 |
| 339 receivedSetNetworkDebugMode: function(status) { |
| 340 for (var i = 0; i < this.setNetworkDebugModeObservers_.length; i++) |
| 341 this.setNetworkDebugModeObservers_[i].onSetNetworkDebugMode(status); |
| 342 }, |
| 343 |
| 344 receivedPrerenderInfo: function(prerenderInfo) { |
| 345 this.pollableDataHelpers_.prerenderInfo.update(prerenderInfo); |
| 346 }, |
| 347 |
| 348 receivedExtensionInfo: function(extensionInfo) { |
| 349 this.pollableDataHelpers_.extensionInfo.update(extensionInfo); |
| 350 }, |
| 351 |
| 352 receivedDataReductionProxyInfo: function(dataReductionProxyInfo) { |
| 353 this.pollableDataHelpers_.dataReductionProxyInfo.update( |
| 354 dataReductionProxyInfo); |
| 355 }, |
| 356 |
| 357 //-------------------------------------------------------------------------- |
| 358 |
| 359 /** |
| 360 * Prevents receiving/sending events to/from the browser. |
| 361 */ |
| 362 disable: function() { |
| 363 this.disabled_ = true; |
| 364 this.setPollInterval(0); |
| 365 }, |
| 366 |
| 367 /** |
| 368 * Returns true if the BrowserBridge has been disabled. |
| 369 */ |
| 370 isDisabled: function() { |
| 371 return this.disabled_; |
| 372 }, |
| 373 |
| 374 /** |
| 375 * Adds a listener of the proxy settings. |observer| will be called back |
| 376 * when data is received, through: |
| 377 * |
| 378 * observer.onProxySettingsChanged(proxySettings) |
| 379 * |
| 380 * |proxySettings| is a dictionary with (up to) two properties: |
| 381 * |
| 382 * "original" -- The settings that chrome was configured to use |
| 383 * (i.e. system settings.) |
| 384 * "effective" -- The "effective" proxy settings that chrome is using. |
| 385 * (decides between the manual/automatic modes of the |
| 386 * fetched settings). |
| 387 * |
| 388 * Each of these two configurations is formatted as a string, and may be |
| 389 * omitted if not yet initialized. |
| 390 * |
| 391 * If |ignoreWhenUnchanged| is true, data is only sent when it changes. |
| 392 * If it's false, data is sent whenever it's received from the browser. |
| 393 */ |
| 394 addProxySettingsObserver: function(observer, ignoreWhenUnchanged) { |
| 395 this.pollableDataHelpers_.proxySettings.addObserver(observer, |
| 396 ignoreWhenUnchanged); |
| 397 }, |
| 398 |
| 399 /** |
| 400 * Adds a listener of the proxy settings. |observer| will be called back |
| 401 * when data is received, through: |
| 402 * |
| 403 * observer.onBadProxiesChanged(badProxies) |
| 404 * |
| 405 * |badProxies| is an array, where each entry has the property: |
| 406 * badProxies[i].proxy_uri: String identify the proxy. |
| 407 * badProxies[i].bad_until: The time when the proxy stops being considered |
| 408 * bad. Note the time is in time ticks. |
| 409 */ |
| 410 addBadProxiesObserver: function(observer, ignoreWhenUnchanged) { |
| 411 this.pollableDataHelpers_.badProxies.addObserver(observer, |
| 412 ignoreWhenUnchanged); |
| 413 }, |
| 414 |
| 415 /** |
| 416 * Adds a listener of the host resolver info. |observer| will be called back |
| 417 * when data is received, through: |
| 418 * |
| 419 * observer.onHostResolverInfoChanged(hostResolverInfo) |
| 420 */ |
| 421 addHostResolverInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 422 this.pollableDataHelpers_.hostResolverInfo.addObserver( |
| 423 observer, ignoreWhenUnchanged); |
| 424 }, |
| 425 |
| 426 /** |
| 427 * Adds a listener of the socket pool. |observer| will be called back |
| 428 * when data is received, through: |
| 429 * |
| 430 * observer.onSocketPoolInfoChanged(socketPoolInfo) |
| 431 */ |
| 432 addSocketPoolInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 433 this.pollableDataHelpers_.socketPoolInfo.addObserver(observer, |
| 434 ignoreWhenUnchanged); |
| 435 }, |
| 436 |
| 437 /** |
| 438 * Adds a listener of the network session. |observer| will be called back |
| 439 * when data is received, through: |
| 440 * |
| 441 * observer.onSessionNetworkStatsChanged(sessionNetworkStats) |
| 442 */ |
| 443 addSessionNetworkStatsObserver: function(observer, ignoreWhenUnchanged) { |
| 444 this.pollableDataHelpers_.sessionNetworkStats.addObserver( |
| 445 observer, ignoreWhenUnchanged); |
| 446 }, |
| 447 |
| 448 /** |
| 449 * Adds a listener of persistent network session data. |observer| will be |
| 450 * called back when data is received, through: |
| 451 * |
| 452 * observer.onHistoricNetworkStatsChanged(historicNetworkStats) |
| 453 */ |
| 454 addHistoricNetworkStatsObserver: function(observer, ignoreWhenUnchanged) { |
| 455 this.pollableDataHelpers_.historicNetworkStats.addObserver( |
| 456 observer, ignoreWhenUnchanged); |
| 457 }, |
| 458 |
| 459 /** |
| 460 * Adds a listener of the QUIC info. |observer| will be called back |
| 461 * when data is received, through: |
| 462 * |
| 463 * observer.onQuicInfoChanged(quicInfo) |
| 464 */ |
| 465 addQuicInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 466 this.pollableDataHelpers_.quicInfo.addObserver( |
| 467 observer, ignoreWhenUnchanged); |
| 468 }, |
| 469 |
| 470 /** |
| 471 * Adds a listener of the SPDY info. |observer| will be called back |
| 472 * when data is received, through: |
| 473 * |
| 474 * observer.onSpdySessionInfoChanged(spdySessionInfo) |
| 475 */ |
| 476 addSpdySessionInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 477 this.pollableDataHelpers_.spdySessionInfo.addObserver( |
| 478 observer, ignoreWhenUnchanged); |
| 479 }, |
| 480 |
| 481 /** |
| 482 * Adds a listener of the SPDY status. |observer| will be called back |
| 483 * when data is received, through: |
| 484 * |
| 485 * observer.onSpdyStatusChanged(spdyStatus) |
| 486 */ |
| 487 addSpdyStatusObserver: function(observer, ignoreWhenUnchanged) { |
| 488 this.pollableDataHelpers_.spdyStatus.addObserver(observer, |
| 489 ignoreWhenUnchanged); |
| 490 }, |
| 491 |
| 492 /** |
| 493 * Adds a listener of the altSvcMappings. |observer| will be |
| 494 * called back when data is received, through: |
| 495 * |
| 496 * observer.onAltSvcMappingsChanged(altSvcMappings) |
| 497 */ |
| 498 addAltSvcMappingsObserver: function(observer, ignoreWhenUnchanged) { |
| 499 this.pollableDataHelpers_.altSvcMappings.addObserver( |
| 500 observer, ignoreWhenUnchanged); |
| 501 }, |
| 502 |
| 503 /** |
| 504 * Adds a listener of the service providers info. |observer| will be called |
| 505 * back when data is received, through: |
| 506 * |
| 507 * observer.onServiceProvidersChanged(serviceProviders) |
| 508 * |
| 509 * Will do nothing if on a platform other than Windows, as service providers |
| 510 * are only present on Windows. |
| 511 */ |
| 512 addServiceProvidersObserver: function(observer, ignoreWhenUnchanged) { |
| 513 if (this.pollableDataHelpers_.serviceProviders) { |
| 514 this.pollableDataHelpers_.serviceProviders.addObserver( |
| 515 observer, ignoreWhenUnchanged); |
| 516 } |
| 517 }, |
| 518 |
| 519 /** |
| 520 * Adds a listener for the progress of the connection tests. |
| 521 * The observer will be called back with: |
| 522 * |
| 523 * observer.onStartedConnectionTestSuite(); |
| 524 * observer.onStartedConnectionTestExperiment(experiment); |
| 525 * observer.onCompletedConnectionTestExperiment(experiment, result); |
| 526 * observer.onCompletedConnectionTestSuite(); |
| 527 */ |
| 528 addConnectionTestsObserver: function(observer) { |
| 529 this.connectionTestsObservers_.push(observer); |
| 530 }, |
| 531 |
| 532 /** |
| 533 * Adds a listener for the http cache info results. |
| 534 * The observer will be called back with: |
| 535 * |
| 536 * observer.onHttpCacheInfoChanged(info); |
| 537 */ |
| 538 addHttpCacheInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 539 this.pollableDataHelpers_.httpCacheInfo.addObserver( |
| 540 observer, ignoreWhenUnchanged); |
| 541 }, |
| 542 |
| 543 /** |
| 544 * Adds a listener for the results of HSTS (HTTPS Strict Transport Security) |
| 545 * queries. The observer will be called back with: |
| 546 * |
| 547 * observer.onHSTSQueryResult(result); |
| 548 */ |
| 549 addHSTSObserver: function(observer) { |
| 550 this.hstsObservers_.push(observer); |
| 551 }, |
| 552 |
| 553 /** |
| 554 * Adds a listener for ONC file parse status. The observer will be called |
| 555 * back with: |
| 556 * |
| 557 * observer.onONCFileParse(error); |
| 558 */ |
| 559 addCrosONCFileParseObserver: function(observer) { |
| 560 this.crosONCFileParseObservers_.push(observer); |
| 561 }, |
| 562 |
| 563 /** |
| 564 * Adds a listener for storing log file status. The observer will be called |
| 565 * back with: |
| 566 * |
| 567 * observer.onStoreDebugLogs(status); |
| 568 */ |
| 569 addStoreDebugLogsObserver: function(observer) { |
| 570 this.storeDebugLogsObservers_.push(observer); |
| 571 }, |
| 572 |
| 573 /** |
| 574 * Adds a listener for network debugging mode status. The observer |
| 575 * will be called back with: |
| 576 * |
| 577 * observer.onSetNetworkDebugMode(status); |
| 578 */ |
| 579 addSetNetworkDebugModeObserver: function(observer) { |
| 580 this.setNetworkDebugModeObservers_.push(observer); |
| 581 }, |
| 582 |
| 583 /** |
| 584 * Adds a listener for the received constants event. |observer| will be |
| 585 * called back when the constants are received, through: |
| 586 * |
| 587 * observer.onReceivedConstants(constants); |
| 588 */ |
| 589 addConstantsObserver: function(observer) { |
| 590 this.constantsObservers_.push(observer); |
| 591 }, |
| 592 |
| 593 /** |
| 594 * Adds a listener for updated prerender info events |
| 595 * |observer| will be called back with: |
| 596 * |
| 597 * observer.onPrerenderInfoChanged(prerenderInfo); |
| 598 */ |
| 599 addPrerenderInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 600 this.pollableDataHelpers_.prerenderInfo.addObserver( |
| 601 observer, ignoreWhenUnchanged); |
| 602 }, |
| 603 |
| 604 /** |
| 605 * Adds a listener of extension information. |observer| will be called |
| 606 * back when data is received, through: |
| 607 * |
| 608 * observer.onExtensionInfoChanged(extensionInfo) |
| 609 */ |
| 610 addExtensionInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 611 this.pollableDataHelpers_.extensionInfo.addObserver( |
| 612 observer, ignoreWhenUnchanged); |
| 613 }, |
| 614 |
| 615 /** |
| 616 * Adds a listener of the data reduction proxy info. |observer| will be |
| 617 * called back when data is received, through: |
| 618 * |
| 619 * observer.onDataReductionProxyInfoChanged(dataReductionProxyInfo) |
| 620 */ |
| 621 addDataReductionProxyInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 622 this.pollableDataHelpers_.dataReductionProxyInfo.addObserver( |
| 623 observer, ignoreWhenUnchanged); |
| 624 }, |
| 625 |
| 626 /** |
| 627 * Adds a listener of SDCH information. |observer| will be called |
| 628 * back when data is received, through: |
| 629 * |
| 630 * observer.onSdchInfoChanged(sdchInfo) |
| 631 */ |
| 632 addSdchInfoObserver: function(observer, ignoreWhenUnchanged) { |
| 633 this.pollableDataHelpers_.sdchInfo.addObserver( |
| 634 observer, ignoreWhenUnchanged); |
| 635 }, |
| 636 |
| 637 /** |
| 638 * If |force| is true, calls all startUpdate functions. Otherwise, just |
| 639 * runs updates with active observers. |
| 640 */ |
| 641 checkForUpdatedInfo: function(force) { |
| 642 for (var name in this.pollableDataHelpers_) { |
| 643 var helper = this.pollableDataHelpers_[name]; |
| 644 if (force || helper.hasActiveObserver()) |
| 645 helper.startUpdate(); |
| 646 } |
| 647 }, |
| 648 |
| 649 /** |
| 650 * Calls all startUpdate functions and, if |callback| is non-null, |
| 651 * calls it with the results of all updates. |
| 652 */ |
| 653 updateAllInfo: function(callback) { |
| 654 if (callback) |
| 655 new UpdateAllObserver(callback, this.pollableDataHelpers_); |
| 656 this.checkForUpdatedInfo(true); |
| 657 }, |
| 658 |
| 659 /** |
| 660 * Adds a PollableDataHelper that listens to the specified NetInfoSource. |
| 661 */ |
| 662 addNetInfoPollableDataHelper: function(sourceName, observerMethodName) { |
| 663 this.pollableDataHelpers_[sourceName] = new PollableDataHelper( |
| 664 observerMethodName, this.sendGetNetInfo.bind(this, sourceName)); |
| 665 }, |
| 666 }; |
| 667 |
| 668 /** |
| 669 * This is a helper class used by BrowserBridge, to keep track of: |
| 670 * - the list of observers interested in some piece of data. |
| 671 * - the last known value of that piece of data. |
| 672 * - the name of the callback method to invoke on observers. |
| 673 * - the update function. |
| 674 * @constructor |
| 675 */ |
| 676 function PollableDataHelper(observerMethodName, startUpdateFunction) { |
| 677 this.observerMethodName_ = observerMethodName; |
| 678 this.startUpdate = startUpdateFunction; |
| 679 this.observerInfos_ = []; |
| 680 } |
| 681 |
| 682 PollableDataHelper.prototype = { |
| 683 getObserverMethodName: function() { |
| 684 return this.observerMethodName_; |
| 685 }, |
| 686 |
| 687 isObserver: function(object) { |
| 688 for (var i = 0; i < this.observerInfos_.length; i++) { |
| 689 if (this.observerInfos_[i].observer === object) |
| 690 return true; |
| 691 } |
| 692 return false; |
| 693 }, |
| 694 |
| 695 /** |
| 696 * If |ignoreWhenUnchanged| is true, we won't send data again until it |
| 697 * changes. |
| 698 */ |
| 699 addObserver: function(observer, ignoreWhenUnchanged) { |
| 700 this.observerInfos_.push(new ObserverInfo(observer, ignoreWhenUnchanged)); |
| 701 }, |
| 702 |
| 703 removeObserver: function(observer) { |
| 704 for (var i = 0; i < this.observerInfos_.length; i++) { |
| 705 if (this.observerInfos_[i].observer === observer) { |
| 706 this.observerInfos_.splice(i, 1); |
| 707 return; |
| 708 } |
| 709 } |
| 710 }, |
| 711 |
| 712 /** |
| 713 * Helper function to handle calling all the observers, but ONLY if the data |
| 714 * has actually changed since last time or the observer has yet to receive |
| 715 * any data. This is used for data we received from browser on an update |
| 716 * loop. |
| 717 */ |
| 718 update: function(data) { |
| 719 var prevData = this.currentData_; |
| 720 var changed = false; |
| 721 |
| 722 // If the data hasn't changed since last time, will only need to notify |
| 723 // observers that have not yet received any data. |
| 724 if (!prevData || JSON.stringify(prevData) != JSON.stringify(data)) { |
| 725 changed = true; |
| 726 this.currentData_ = data; |
| 727 } |
| 728 |
| 729 // Notify the observers of the change, as needed. |
| 730 for (var i = 0; i < this.observerInfos_.length; i++) { |
| 731 var observerInfo = this.observerInfos_[i]; |
| 732 if (changed || !observerInfo.hasReceivedData || |
| 733 !observerInfo.ignoreWhenUnchanged) { |
| 734 observerInfo.observer[this.observerMethodName_](this.currentData_); |
| 735 observerInfo.hasReceivedData = true; |
| 736 } |
| 737 } |
| 738 }, |
| 739 |
| 740 /** |
| 741 * Returns true if one of the observers actively wants the data |
| 742 * (i.e. is visible). |
| 743 */ |
| 744 hasActiveObserver: function() { |
| 745 for (var i = 0; i < this.observerInfos_.length; i++) { |
| 746 if (this.observerInfos_[i].observer.isActive()) |
| 747 return true; |
| 748 } |
| 749 return false; |
| 750 } |
| 751 }; |
| 752 |
| 753 /** |
| 754 * This is a helper class used by PollableDataHelper, to keep track of |
| 755 * each observer and whether or not it has received any data. The |
| 756 * latter is used to make sure that new observers get sent data on the |
| 757 * update following their creation. |
| 758 * @constructor |
| 759 */ |
| 760 function ObserverInfo(observer, ignoreWhenUnchanged) { |
| 761 this.observer = observer; |
| 762 this.hasReceivedData = false; |
| 763 this.ignoreWhenUnchanged = ignoreWhenUnchanged; |
| 764 } |
| 765 |
| 766 /** |
| 767 * This is a helper class used by BrowserBridge to send data to |
| 768 * a callback once data from all polls has been received. |
| 769 * |
| 770 * It works by keeping track of how many polling functions have |
| 771 * yet to receive data, and recording the data as it it received. |
| 772 * |
| 773 * @constructor |
| 774 */ |
| 775 function UpdateAllObserver(callback, pollableDataHelpers) { |
| 776 this.callback_ = callback; |
| 777 this.observingCount_ = 0; |
| 778 this.updatedData_ = {}; |
| 779 |
| 780 for (var name in pollableDataHelpers) { |
| 781 ++this.observingCount_; |
| 782 var helper = pollableDataHelpers[name]; |
| 783 helper.addObserver(this); |
| 784 this[helper.getObserverMethodName()] = |
| 785 this.onDataReceived_.bind(this, helper, name); |
| 786 } |
| 787 } |
| 788 |
| 789 UpdateAllObserver.prototype = { |
| 790 isActive: function() { |
| 791 return true; |
| 792 }, |
| 793 |
| 794 onDataReceived_: function(helper, name, data) { |
| 795 helper.removeObserver(this); |
| 796 --this.observingCount_; |
| 797 this.updatedData_[name] = data; |
| 798 if (this.observingCount_ == 0) |
| 799 this.callback_(this.updatedData_); |
| 800 } |
| 801 }; |
| 802 |
| 803 return BrowserBridge; |
| 804 })(); |
| 805 |
OLD | NEW |