~ubuntu-branches/ubuntu/gutsy/firefox/gutsy

« back to all changes in this revision

Viewing changes to browser/components/safebrowsing/content/phishing-warden.js

  • Committer: Bazaar Package Importer
  • Author(s): Ian Jackson
  • Date: 2006-10-10 18:49:32 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20061010184932-da75izt7y0e59afq
Tags: 1.99+2.0rc2+dfsg-0ubuntu1
* New upstream version 2.0rc2.
* Fix/workaround for epiphany GtkSocket lifetype crash:
  apply patch id=241087 from Mozilla Bugzilla #241535 to fix LP #63814.
* Change application name to `Firefox', as requested by mdz.
  Files changed:
    - browser/locales/en-US/chrome/branding/brand.dtd
    - browser/locales/en-US/chrome/branding/brand.properties;
  New values:
    - brandShortName and brandFullName: `Bon Echo' => `Firefox'
    - vendorShortName: `Mozilla' => `Ubuntu'
* Make preferences dialogue fit again (bah!).

Show diffs side-by-side

added added

removed removed

Lines of Context:
105
105
 
106
106
  // Read state: should we be checking remote preferences?
107
107
  this.checkRemote_ = this.prefs_.getPref(kPhishWardenRemoteLookups, null);
 
108
  
 
109
  // true if we should use whitelists to suppress remote lookups
 
110
  this.checkWhitelists_ = false;
108
111
 
109
112
  // Get notifications when the remote check preference changes
110
113
  var checkRemotePrefObserver = BindToObject(this.onCheckRemotePrefChanged,
118
121
  var phishWardenPrefObserver = 
119
122
    BindToObject(this.onPhishWardenEnabledPrefChanged, this);
120
123
  this.prefs_.addObserver(kPhishWardenEnabledPref, phishWardenPrefObserver);
 
124
  
 
125
  // Get notifications when the data provider pref changes
 
126
  var dataProviderPrefObserver =
 
127
    BindToObject(this.onDataProviderPrefChanged, this);
 
128
  this.prefs_.addObserver(kDataProviderIdPref, dataProviderPrefObserver);
121
129
 
122
130
  // hook up our browser listener
123
131
  this.progressListener_ = progressListener;
126
134
  // ms to wait after a request has started before firing JS callback
127
135
  this.progressListener_.delay = 1500;
128
136
 
 
137
  // object to keep track of request errors if we're in remote check mode
 
138
  this.requestBackoff_ = new RequestBackoff(3 /* num errors */,
 
139
                                   10*60*1000 /* error time, 10min */,
 
140
                                   10*60*1000 /* backoff interval, 10min */,
 
141
                                   6*60*60*1000 /* max backoff, 6hr */);
 
142
 
129
143
  G_Debug(this, "phishWarden initialized");
130
144
}
131
145
 
181
195
 
182
196
  // We update and save to disk all tables if we don't have remote checking
183
197
  // enabled.
184
 
  if (phishWardenEnabled === true && this.checkRemote_ === false) {
 
198
  if (phishWardenEnabled === true) {
 
199
    // If anti-phishing is enabled, we always download the local files to
 
200
    // use in case remote lookups fail.
185
201
    this.enableBlacklistTableUpdates();
186
202
    this.enableWhitelistTableUpdates();
 
203
 
 
204
    if (this.checkRemote_ === true) {
 
205
      // Remote lookup mode
 
206
      // We check to see if the local list update host is the same as the
 
207
      // remote lookup host.  If they are the same, then we don't bother
 
208
      // to do a remote url check if the url is in the whitelist.
 
209
      var ioService = Cc["@mozilla.org/network/io-service;1"]
 
210
                     .getService(Ci.nsIIOService);
 
211
      var updateHost = '';
 
212
      var lookupHost = '';
 
213
      try {
 
214
        var url = ioService.newURI(gDataProvider.getUpdateURL(),
 
215
                                         null, null);
 
216
        updateHost = url.asciiHost;
 
217
      } catch (e) { }
 
218
      try {
 
219
        var url = ioService.newURI(gDataProvider.getLookupURL(),
 
220
                                         null, null);
 
221
        lookupHost = url.asciiHost;
 
222
      } catch (e) { }
 
223
 
 
224
      if (updateHost && lookupHost && updateHost == lookupHost) {
 
225
        // The data provider for local lists and remote lookups is the
 
226
        // same, enable whitelist lookup suppression.
 
227
        this.checkWhitelists_ = true;
 
228
      } else {
 
229
        // hosts don't match, don't use whitelist suppression
 
230
        this.checkWhitelists_ = false;
 
231
      }
 
232
    }
187
233
  } else {
 
234
    // Anti-phishing is off, disable table updates
188
235
    this.disableBlacklistTableUpdates();
189
236
    this.disableWhitelistTableUpdates();
190
237
  }
225
272
PROT_PhishingWarden.prototype.onCheckRemotePrefChanged = function(prefName) {
226
273
  this.checkRemote_ = this.prefs_.getBoolPrefOrDefault(prefName,
227
274
                                                       this.checkRemote_);
 
275
  this.requestBackoff_.reset();
228
276
  this.maybeToggleUpdateChecking();
229
277
}
230
278
 
239
287
                                                                    prefName) {
240
288
  this.phishWardenEnabled_ = 
241
289
    this.prefs_.getBoolPrefOrDefault(prefName, this.phishWardenEnabled_);
 
290
  this.requestBackoff_.reset();
242
291
  this.maybeToggleUpdateChecking();
243
292
  this.progressListener_.enabled = this.phishWardenEnabled_;
244
293
}
245
294
 
246
295
/**
 
296
 * Event fired when the user changes data providers.
 
297
 */
 
298
PROT_PhishingWarden.prototype.onDataProviderPrefChanged = function(prefName) {
 
299
  // We want to reset request backoff state since it's a different provider.
 
300
  this.requestBackoff_.reset();
 
301
 
 
302
  // If we have a new data provider and we're doing remote lookups, then
 
303
  // we may want to use whitelist lookup suppression or change which
 
304
  // tables are being downloaded.
 
305
  if (this.checkRemote_) {
 
306
    this.maybeToggleUpdateChecking();
 
307
  }
 
308
}
 
309
 
 
310
/**
247
311
 * A request for a Document has been initiated somewhere. Check it!
248
312
 *
249
313
 * @param request
253
317
  G_Debug(this, "checkRemote: " +
254
318
          (this.checkRemote_ ? "yes" : "no"));
255
319
 
256
 
  // This logic is a bit involved. In some instances of SafeBrowsing
257
 
  // (the stand-alone extension, for example), the user might yet have
258
 
  // opted into or out of advanced protection mode. In this case we
259
 
  // would like to show them a modal dialog requiring them
260
 
  // to. However, there are links from that dialog to the test page,
261
 
  // and the warden starts out as disabled. So we want to show the
262
 
  // warning on the test page so long as the extension hasn't been
263
 
  // explicitly disabled.
264
 
 
265
 
  // If we're on the test page and we're not explicitly disabled
 
320
  // If we're on a test page, trigger the warning.
266
321
  // XXX Do we still need a test url or should each provider just put
267
322
  // it in their local list?
268
 
  // Either send a request off or check locally
269
 
  if (this.checkRemote_) {
270
 
    // First check to see if it's a blacklist url.
271
 
    if (this.isBlacklistTestURL(url)) {
272
 
      this.houstonWeHaveAProblem_(request);
 
323
  if (this.isBlacklistTestURL(url)) {
 
324
    this.houstonWeHaveAProblem_(request);
 
325
    return;
 
326
  }
 
327
 
 
328
  // Make a remote lookup check if the pref is selected and if we haven't
 
329
  // triggered server backoff.  Otherwise, make a local check.
 
330
  if (this.checkRemote_ && this.requestBackoff_.canMakeRequest()) {
 
331
    // If we can use whitelists to suppress remote lookups, do so.
 
332
    if (this.checkWhitelists_) {
 
333
      var maybeRemoteCheck = BindToObject(this.maybeMakeRemoteCheck_,
 
334
                                          this,
 
335
                                          url,
 
336
                                          request);
 
337
      this.isWhiteURL(url, maybeRemoteCheck);
273
338
    } else {
274
 
      // TODO: Use local whitelists to suppress remote BL lookups. 
 
339
      // Do a remote lookup (don't check whitelists)
275
340
      this.fetcher_.get(url,
276
341
                        BindToObject(this.onTRFetchComplete,
277
342
                                     this,
 
343
                                     url,
278
344
                                     request));
279
345
    }
280
346
  } else {
283
349
                                    this,
284
350
                                    url,
285
351
                                    request);
286
 
    this.checkUrl_(url, evilCallback);
 
352
    this.isEvilURL(url, evilCallback);
287
353
  }
288
354
}
289
355
 
 
356
/** 
 
357
 * Callback from whitelist check when remote lookups is on.
 
358
 * @param url String url to lookup
 
359
 * @param request nsIRequest object
 
360
 * @param status int enum from callback (PROT_ListWarden.IN_BLACKLIST,
 
361
 *    PROT_ListWarden.IN_WHITELIST, PROT_ListWarden.NOT_FOUND)
 
362
 */
 
363
PROT_PhishingWarden.prototype.maybeMakeRemoteCheck_ = function(url, request, status) {
 
364
  if (PROT_ListWarden.IN_WHITELIST == status)
 
365
    return;
 
366
 
 
367
  G_Debug(this, "Local whitelist lookup failed");
 
368
  this.fetcher_.get(url,
 
369
                    BindToObject(this.onTRFetchComplete,
 
370
                                 this,
 
371
                                 url,
 
372
                                 request));
 
373
}
 
374
 
290
375
/**
291
376
 * Invoked with the result of a lookupserver request.
292
377
 *
 
378
 * @param url String the URL we looked up
293
379
 * @param request The nsIRequest in which we're interested
294
 
 *
295
380
 * @param trValues Object holding name/value pairs parsed from the
296
381
 *                 lookupserver's response
 
382
 * @param status Number HTTP status code or NS_ERROR_NOT_AVAILABLE if there's
 
383
 *               an HTTP error
297
384
 */
298
 
PROT_PhishingWarden.prototype.onTRFetchComplete = function(request,
299
 
                                                           trValues) {
300
 
  var callback = BindToObject(this.houstonWeHaveAProblem_, this, request);
301
 
  this.checkRemoteData(callback, trValues);
 
385
PROT_PhishingWarden.prototype.onTRFetchComplete = function(url,
 
386
                                                           request,
 
387
                                                           trValues,
 
388
                                                           status) {
 
389
  // Did the remote http request succeed?  If not, we fall back on
 
390
  // local lists.
 
391
  if (status == Components.results.NS_ERROR_NOT_AVAILABLE ||
 
392
      this.requestBackoff_.isErrorStatus_(status)) {
 
393
    this.requestBackoff_.noteServerResponse(status);
 
394
 
 
395
    G_Debug(this, "remote check failed, using local lists instead");
 
396
    var evilCallback = BindToObject(this.localListMatch_,
 
397
                                    this,
 
398
                                    url,
 
399
                                    request);
 
400
    this.isEvilURL(url, evilCallback);
 
401
  } else {
 
402
    var callback = BindToObject(this.houstonWeHaveAProblem_, this, request);
 
403
    this.checkRemoteData(callback, trValues);
 
404
  }
302
405
}
303
406
 
304
407
/**
431
534
}
432
535
 
433
536
/**
434
 
 * Check to see if the url is in the blacklist.
435
 
 *
436
 
 * @param url String
437
 
 * @param callback Function
438
 
 */
439
 
PROT_PhishingWarden.prototype.checkUrl_ = function(url, callback) {
440
 
  // First check to see if it's a blacklist url.
441
 
  if (this.isBlacklistTestURL(url)) {
442
 
    callback();
443
 
    return;
444
 
  }
445
 
  this.isEvilURL_(url, callback);
446
 
}
447
 
 
448
 
/**
449
537
 * Callback for found local blacklist match.  First we report that we have
450
538
 * a blacklist hit, then we bring up the warning dialog.
 
539
 * @param status Number enum from callback (PROT_ListWarden.IN_BLACKLIST,
 
540
 *    PROT_ListWarden.IN_WHITELIST, PROT_ListWarden.NOT_FOUND)
451
541
 */
452
 
PROT_PhishingWarden.prototype.localListMatch_ = function(url, request) {
 
542
PROT_PhishingWarden.prototype.localListMatch_ = function(url, request, status) {
 
543
  if (PROT_ListWarden.IN_BLACKLIST != status)
 
544
    return;
 
545
 
453
546
  // Maybe send a report
454
547
  (new PROT_Reporter).report("phishblhit", url);
455
548
  this.houstonWeHaveAProblem_(request);
479
572
    G_Debug(this, "Remote blacklist miss");
480
573
  }
481
574
}
 
575
 
 
576
#ifdef 0
 
577
// Some unittests (e.g., paste into JS shell)
 
578
var warden = safebrowsing.phishWarden;
 
579
function expectLocalCheck() {
 
580
  warden.isEvilURL = function() {
 
581
    dump("checkurl: ok\n");
 
582
  }
 
583
  warden.checkRemoteData = function() {
 
584
    throw "unexpected remote check";
 
585
  }
 
586
}
 
587
function expectRemoteCheck() {
 
588
  warden.isEvilURL = function() {
 
589
    throw "unexpected local check";
 
590
  }
 
591
  warden.checkRemoteData = function() {
 
592
    dump("checkremote: ok\n");
 
593
  }
 
594
}
 
595
 
 
596
warden.requestBackoff_.reset();
 
597
 
 
598
// START TESTS
 
599
expectRemoteCheck();
 
600
warden.onTRFetchComplete(null, null, null, 200);
 
601
 
 
602
// HTTP 5xx should fallback on local check
 
603
expectLocalCheck();
 
604
warden.onTRFetchComplete(null, null, null, 500);
 
605
warden.onTRFetchComplete(null, null, null, 502);
 
606
 
 
607
// Only two errors have occurred, so we continue to try remote lookups.
 
608
if (!warden.requestBackoff_.canMakeRequest()) throw "expected ok";
 
609
 
 
610
// NS_ERROR_NOT_AVAILABLE also triggers a local check, but it doesn't
 
611
// count as a remote lookup error.  We don't know /why/ it failed (e.g.,
 
612
// user may just be in offline mode).
 
613
warden.onTRFetchComplete(null, null, null,
 
614
                         Components.results.NS_ERROR_NOT_AVAILABLE);
 
615
if (!warden.requestBackoff_.canMakeRequest()) throw "expected ok";
 
616
 
 
617
// HTTP 302, 303, 307 should also trigger an error.  This is our
 
618
// third error so we should now be in backoff mode.
 
619
expectLocalCheck();
 
620
warden.onTRFetchComplete(null, null, null, 303);
 
621
 
 
622
if (warden.requestBackoff_.canMakeRequest()) throw "expected failed";
 
623
 
 
624
#endif