1 : //* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Url Classifier code
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Google Inc.
19 : * Portions created by the Initial Developer are Copyright (C) 2006
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Tony Chang <tony@ponderer.org> (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsCRT.h"
40 : #include "nsIHttpChannel.h"
41 : #include "nsIObserverService.h"
42 : #include "nsIStringStream.h"
43 : #include "nsIUploadChannel.h"
44 : #include "nsIURI.h"
45 : #include "nsIUrlClassifierDBService.h"
46 : #include "nsStreamUtils.h"
47 : #include "nsStringStream.h"
48 : #include "nsToolkitCompsCID.h"
49 : #include "nsUrlClassifierStreamUpdater.h"
50 : #include "prlog.h"
51 :
52 : static const char* gQuitApplicationMessage = "quit-application";
53 :
54 : // NSPR_LOG_MODULES=UrlClassifierStreamUpdater:5
55 : #if defined(PR_LOGGING)
56 : static const PRLogModuleInfo *gUrlClassifierStreamUpdaterLog = nsnull;
57 : #define LOG(args) PR_LOG(gUrlClassifierStreamUpdaterLog, PR_LOG_DEBUG, args)
58 : #else
59 : #define LOG(args)
60 : #endif
61 :
62 :
63 : ///////////////////////////////////////////////////////////////////////////////
64 : // nsIUrlClassiferStreamUpdater implementation
65 : // Handles creating/running the stream listener
66 :
67 7 : nsUrlClassifierStreamUpdater::nsUrlClassifierStreamUpdater()
68 : : mIsUpdating(false), mInitialized(false), mDownloadError(false),
69 7 : mBeganStream(false), mUpdateUrl(nsnull), mChannel(nsnull)
70 : {
71 : #if defined(PR_LOGGING)
72 7 : if (!gUrlClassifierStreamUpdaterLog)
73 7 : gUrlClassifierStreamUpdaterLog = PR_NewLogModule("UrlClassifierStreamUpdater");
74 : #endif
75 :
76 7 : }
77 :
78 2392 : NS_IMPL_THREADSAFE_ISUPPORTS9(nsUrlClassifierStreamUpdater,
79 : nsIUrlClassifierStreamUpdater,
80 : nsIUrlClassifierUpdateObserver,
81 : nsIRequestObserver,
82 : nsIStreamListener,
83 : nsIObserver,
84 : nsIBadCertListener2,
85 : nsISSLErrorListener,
86 : nsIInterfaceRequestor,
87 : nsITimerCallback)
88 :
89 : /**
90 : * Clear out the update.
91 : */
92 : void
93 72 : nsUrlClassifierStreamUpdater::DownloadDone()
94 : {
95 72 : LOG(("nsUrlClassifierStreamUpdater::DownloadDone [this=%p]", this));
96 72 : mIsUpdating = false;
97 :
98 72 : mPendingUpdates.Clear();
99 72 : mDownloadError = false;
100 72 : mSuccessCallback = nsnull;
101 72 : mUpdateErrorCallback = nsnull;
102 72 : mDownloadErrorCallback = nsnull;
103 72 : }
104 :
105 : ///////////////////////////////////////////////////////////////////////////////
106 : // nsIUrlClassifierStreamUpdater implementation
107 :
108 : NS_IMETHODIMP
109 0 : nsUrlClassifierStreamUpdater::GetUpdateUrl(nsACString & aUpdateUrl)
110 : {
111 0 : if (mUpdateUrl) {
112 0 : mUpdateUrl->GetSpec(aUpdateUrl);
113 : } else {
114 0 : aUpdateUrl.Truncate();
115 : }
116 0 : return NS_OK;
117 : }
118 :
119 : NS_IMETHODIMP
120 72 : nsUrlClassifierStreamUpdater::SetUpdateUrl(const nsACString & aUpdateUrl)
121 : {
122 72 : LOG(("Update URL is %s\n", PromiseFlatCString(aUpdateUrl).get()));
123 :
124 72 : nsresult rv = NS_NewURI(getter_AddRefs(mUpdateUrl), aUpdateUrl);
125 72 : NS_ENSURE_SUCCESS(rv, rv);
126 :
127 72 : return NS_OK;
128 : }
129 :
130 : nsresult
131 86 : nsUrlClassifierStreamUpdater::FetchUpdate(nsIURI *aUpdateUrl,
132 : const nsACString & aRequestBody,
133 : const nsACString & aStreamTable,
134 : const nsACString & aServerMAC)
135 : {
136 : nsresult rv;
137 : PRUint32 loadFlags = nsIChannel::INHIBIT_CACHING |
138 86 : nsIChannel::LOAD_BYPASS_CACHE;
139 86 : rv = NS_NewChannel(getter_AddRefs(mChannel), aUpdateUrl, nsnull, nsnull, this,
140 86 : loadFlags);
141 86 : NS_ENSURE_SUCCESS(rv, rv);
142 :
143 86 : mBeganStream = false;
144 :
145 86 : if (!aRequestBody.IsEmpty()) {
146 0 : rv = AddRequestBody(aRequestBody);
147 0 : NS_ENSURE_SUCCESS(rv, rv);
148 : }
149 :
150 : // Set the appropriate content type for file/data URIs, for unit testing
151 : // purposes.
152 : bool match;
153 172 : if ((NS_SUCCEEDED(aUpdateUrl->SchemeIs("file", &match)) && match) ||
154 86 : (NS_SUCCEEDED(aUpdateUrl->SchemeIs("data", &match)) && match)) {
155 84 : mChannel->SetContentType(NS_LITERAL_CSTRING("application/vnd.google.safebrowsing-update"));
156 : }
157 :
158 : // Make the request
159 86 : rv = mChannel->AsyncOpen(this, nsnull);
160 86 : NS_ENSURE_SUCCESS(rv, rv);
161 :
162 86 : mStreamTable = aStreamTable;
163 86 : mServerMAC = aServerMAC;
164 :
165 86 : return NS_OK;
166 : }
167 :
168 : nsresult
169 14 : nsUrlClassifierStreamUpdater::FetchUpdate(const nsACString & aUpdateUrl,
170 : const nsACString & aRequestBody,
171 : const nsACString & aStreamTable,
172 : const nsACString & aServerMAC)
173 : {
174 14 : LOG(("(pre) Fetching update from %s\n", PromiseFlatCString(aUpdateUrl).get()));
175 :
176 28 : nsCOMPtr<nsIURI> uri;
177 14 : nsresult rv = NS_NewURI(getter_AddRefs(uri), aUpdateUrl);
178 14 : NS_ENSURE_SUCCESS(rv, rv);
179 :
180 28 : nsCAutoString urlSpec;
181 14 : uri->GetAsciiSpec(urlSpec);
182 :
183 14 : LOG(("(post) Fetching update from %s\n", urlSpec.get()));
184 :
185 14 : return FetchUpdate(uri, aRequestBody, aStreamTable, aServerMAC);
186 : }
187 :
188 : NS_IMETHODIMP
189 72 : nsUrlClassifierStreamUpdater::DownloadUpdates(
190 : const nsACString &aRequestTables,
191 : const nsACString &aRequestBody,
192 : const nsACString &aClientKey,
193 : nsIUrlClassifierCallback *aSuccessCallback,
194 : nsIUrlClassifierCallback *aUpdateErrorCallback,
195 : nsIUrlClassifierCallback *aDownloadErrorCallback,
196 : bool *_retval)
197 : {
198 72 : NS_ENSURE_ARG(aSuccessCallback);
199 72 : NS_ENSURE_ARG(aUpdateErrorCallback);
200 72 : NS_ENSURE_ARG(aDownloadErrorCallback);
201 :
202 72 : if (mIsUpdating) {
203 0 : LOG(("already updating, skipping update"));
204 0 : *_retval = false;
205 0 : return NS_OK;
206 : }
207 :
208 72 : if (!mUpdateUrl) {
209 0 : NS_ERROR("updateUrl not set");
210 0 : return NS_ERROR_NOT_INITIALIZED;
211 : }
212 :
213 : nsresult rv;
214 :
215 72 : if (!mInitialized) {
216 : // Add an observer for shutdown so we can cancel any pending list
217 : // downloads. quit-application is the same event that the download
218 : // manager listens for and uses to cancel pending downloads.
219 : nsCOMPtr<nsIObserverService> observerService =
220 6 : mozilla::services::GetObserverService();
221 3 : if (!observerService)
222 0 : return NS_ERROR_FAILURE;
223 :
224 3 : observerService->AddObserver(this, gQuitApplicationMessage, false);
225 :
226 3 : mDBService = do_GetService(NS_URLCLASSIFIERDBSERVICE_CONTRACTID, &rv);
227 3 : NS_ENSURE_SUCCESS(rv, rv);
228 :
229 6 : mInitialized = true;
230 : }
231 :
232 72 : rv = mDBService->BeginUpdate(this, aRequestTables, aClientKey);
233 72 : if (rv == NS_ERROR_NOT_AVAILABLE) {
234 0 : LOG(("already updating, skipping update"));
235 0 : *_retval = false;
236 0 : return NS_OK;
237 72 : } else if (NS_FAILED(rv)) {
238 0 : return rv;
239 : }
240 :
241 72 : mSuccessCallback = aSuccessCallback;
242 72 : mUpdateErrorCallback = aUpdateErrorCallback;
243 72 : mDownloadErrorCallback = aDownloadErrorCallback;
244 :
245 72 : mIsUpdating = true;
246 72 : *_retval = true;
247 :
248 144 : nsCAutoString urlSpec;
249 72 : mUpdateUrl->GetAsciiSpec(urlSpec);
250 :
251 72 : LOG(("FetchUpdate: %s", urlSpec.get()));
252 : //LOG(("requestBody: %s", aRequestBody.get()));
253 :
254 72 : return FetchUpdate(mUpdateUrl, aRequestBody, EmptyCString(), EmptyCString());
255 : }
256 :
257 : ///////////////////////////////////////////////////////////////////////////////
258 : // nsIUrlClassifierUpdateObserver implementation
259 :
260 : NS_IMETHODIMP
261 16 : nsUrlClassifierStreamUpdater::UpdateUrlRequested(const nsACString &aUrl,
262 : const nsACString &aTable,
263 : const nsACString &aServerMAC)
264 : {
265 16 : LOG(("Queuing requested update from %s\n", PromiseFlatCString(aUrl).get()));
266 :
267 16 : PendingUpdate *update = mPendingUpdates.AppendElement();
268 16 : if (!update)
269 0 : return NS_ERROR_OUT_OF_MEMORY;
270 :
271 : // Allow data: and file: urls for unit testing purposes, otherwise assume http
272 36 : if (StringBeginsWith(aUrl, NS_LITERAL_CSTRING("data:")) ||
273 20 : StringBeginsWith(aUrl, NS_LITERAL_CSTRING("file:"))) {
274 14 : update->mUrl = aUrl;
275 : } else {
276 2 : update->mUrl = NS_LITERAL_CSTRING("http://") + aUrl;
277 : }
278 16 : update->mTable = aTable;
279 16 : update->mServerMAC = aServerMAC;
280 :
281 16 : return NS_OK;
282 : }
283 :
284 : NS_IMETHODIMP
285 1 : nsUrlClassifierStreamUpdater::RekeyRequested()
286 : {
287 : nsCOMPtr<nsIObserverService> observerService =
288 2 : mozilla::services::GetObserverService();
289 :
290 1 : if (!observerService)
291 0 : return NS_ERROR_FAILURE;
292 :
293 1 : return observerService->NotifyObservers(static_cast<nsIUrlClassifierStreamUpdater*>(this),
294 : "url-classifier-rekey-requested",
295 1 : nsnull);
296 : }
297 :
298 : nsresult
299 14 : nsUrlClassifierStreamUpdater::FetchNext()
300 : {
301 14 : if (mPendingUpdates.Length() == 0) {
302 0 : return NS_OK;
303 : }
304 :
305 14 : PendingUpdate &update = mPendingUpdates[0];
306 14 : LOG(("Fetching update url: %s\n", update.mUrl.get()));
307 14 : nsresult rv = FetchUpdate(update.mUrl, EmptyCString(),
308 28 : update.mTable, update.mServerMAC);
309 14 : if (NS_FAILED(rv)) {
310 0 : LOG(("Error fetching update url: %s\n", update.mUrl.get()));
311 : // We can commit the urls that we've applied so far. This is
312 : // probably a transient server problem, so trigger backoff.
313 0 : mDownloadErrorCallback->HandleEvent(EmptyCString());
314 0 : mDownloadError = true;
315 0 : mDBService->FinishUpdate();
316 0 : return rv;
317 : }
318 :
319 14 : mPendingUpdates.RemoveElementAt(0);
320 :
321 14 : return NS_OK;
322 : }
323 :
324 : NS_IMETHODIMP
325 84 : nsUrlClassifierStreamUpdater::StreamFinished(nsresult status,
326 : PRUint32 requestedDelay)
327 : {
328 84 : LOG(("nsUrlClassifierStreamUpdater::StreamFinished [%x, %d]", status, requestedDelay));
329 84 : if (NS_FAILED(status) || mPendingUpdates.Length() == 0) {
330 : // We're done.
331 70 : mDBService->FinishUpdate();
332 70 : return NS_OK;
333 : }
334 :
335 : // Wait the requested amount of time before starting a new stream.
336 : nsresult rv;
337 14 : mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
338 14 : if (NS_SUCCEEDED(rv)) {
339 14 : rv = mTimer->InitWithCallback(this, requestedDelay,
340 14 : nsITimer::TYPE_ONE_SHOT);
341 : }
342 :
343 14 : if (NS_FAILED(rv)) {
344 0 : NS_WARNING("Unable to initialize timer, fetching next safebrowsing item immediately");
345 0 : return FetchNext();
346 : }
347 :
348 14 : return NS_OK;
349 : }
350 :
351 : NS_IMETHODIMP
352 65 : nsUrlClassifierStreamUpdater::UpdateSuccess(PRUint32 requestedTimeout)
353 : {
354 65 : LOG(("nsUrlClassifierStreamUpdater::UpdateSuccess [this=%p]", this));
355 65 : if (mPendingUpdates.Length() != 0) {
356 0 : NS_WARNING("Didn't fetch all safebrowsing update redirects");
357 : }
358 :
359 : // DownloadDone() clears mSuccessCallback, so we save it off here.
360 130 : nsCOMPtr<nsIUrlClassifierCallback> successCallback = mDownloadError ? nsnull : mSuccessCallback.get();
361 65 : DownloadDone();
362 :
363 130 : nsCAutoString strTimeout;
364 65 : strTimeout.AppendInt(requestedTimeout);
365 65 : if (successCallback) {
366 65 : successCallback->HandleEvent(strTimeout);
367 : }
368 :
369 65 : return NS_OK;
370 : }
371 :
372 : NS_IMETHODIMP
373 7 : nsUrlClassifierStreamUpdater::UpdateError(PRUint32 result)
374 : {
375 7 : LOG(("nsUrlClassifierStreamUpdater::UpdateError [this=%p]", this));
376 :
377 : // DownloadDone() clears mUpdateErrorCallback, so we save it off here.
378 14 : nsCOMPtr<nsIUrlClassifierCallback> errorCallback = mDownloadError ? nsnull : mUpdateErrorCallback.get();
379 :
380 7 : DownloadDone();
381 :
382 14 : nsCAutoString strResult;
383 7 : strResult.AppendInt(result);
384 7 : if (errorCallback) {
385 7 : errorCallback->HandleEvent(strResult);
386 : }
387 :
388 7 : return NS_OK;
389 : }
390 :
391 : nsresult
392 0 : nsUrlClassifierStreamUpdater::AddRequestBody(const nsACString &aRequestBody)
393 : {
394 : nsresult rv;
395 : nsCOMPtr<nsIStringInputStream> strStream =
396 0 : do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID, &rv);
397 0 : NS_ENSURE_SUCCESS(rv, rv);
398 :
399 0 : rv = strStream->SetData(aRequestBody.BeginReading(),
400 0 : aRequestBody.Length());
401 0 : NS_ENSURE_SUCCESS(rv, rv);
402 :
403 0 : nsCOMPtr<nsIUploadChannel> uploadChannel = do_QueryInterface(mChannel, &rv);
404 0 : NS_ENSURE_SUCCESS(rv, rv);
405 :
406 0 : rv = uploadChannel->SetUploadStream(strStream,
407 0 : NS_LITERAL_CSTRING("text/plain"),
408 0 : -1);
409 0 : NS_ENSURE_SUCCESS(rv, rv);
410 :
411 0 : nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel, &rv);
412 0 : NS_ENSURE_SUCCESS(rv, rv);
413 :
414 0 : rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
415 0 : NS_ENSURE_SUCCESS(rv, rv);
416 :
417 0 : return NS_OK;
418 : }
419 :
420 :
421 : ///////////////////////////////////////////////////////////////////////////////
422 : // nsIStreamListenerObserver implementation
423 :
424 : NS_IMETHODIMP
425 86 : nsUrlClassifierStreamUpdater::OnStartRequest(nsIRequest *request,
426 : nsISupports* context)
427 : {
428 : nsresult rv;
429 86 : bool downloadError = false;
430 172 : nsCAutoString strStatus;
431 86 : nsresult status = NS_OK;
432 :
433 : // Only update if we got http success header
434 172 : nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
435 86 : if (httpChannel) {
436 2 : rv = httpChannel->GetStatus(&status);
437 2 : NS_ENSURE_SUCCESS(rv, rv);
438 :
439 2 : if (NS_ERROR_CONNECTION_REFUSED == status ||
440 : NS_ERROR_NET_TIMEOUT == status) {
441 : // Assume we're overloading the server and trigger backoff.
442 0 : downloadError = true;
443 : }
444 :
445 2 : if (NS_SUCCEEDED(status)) {
446 0 : bool succeeded = false;
447 0 : rv = httpChannel->GetRequestSucceeded(&succeeded);
448 0 : NS_ENSURE_SUCCESS(rv, rv);
449 :
450 0 : if (!succeeded) {
451 : // 404 or other error, pass error status back
452 0 : LOG(("HTTP request returned failure code."));
453 :
454 0 : rv = httpChannel->GetResponseStatus(&status);
455 0 : NS_ENSURE_SUCCESS(rv, rv);
456 :
457 0 : strStatus.AppendInt(status);
458 0 : downloadError = true;
459 : }
460 : }
461 : }
462 :
463 86 : if (downloadError) {
464 0 : mDownloadErrorCallback->HandleEvent(strStatus);
465 0 : mDownloadError = true;
466 0 : status = NS_ERROR_ABORT;
467 86 : } else if (NS_SUCCEEDED(status)) {
468 84 : mBeganStream = true;
469 84 : rv = mDBService->BeginStream(mStreamTable, mServerMAC);
470 84 : NS_ENSURE_SUCCESS(rv, rv);
471 : }
472 :
473 86 : mStreamTable.Truncate();
474 86 : mServerMAC.Truncate();
475 :
476 86 : return status;
477 : }
478 :
479 : NS_IMETHODIMP
480 84 : nsUrlClassifierStreamUpdater::OnDataAvailable(nsIRequest *request,
481 : nsISupports* context,
482 : nsIInputStream *aIStream,
483 : PRUint32 aSourceOffset,
484 : PRUint32 aLength)
485 : {
486 84 : if (!mDBService)
487 0 : return NS_ERROR_NOT_INITIALIZED;
488 :
489 84 : LOG(("OnDataAvailable (%d bytes)", aLength));
490 :
491 : nsresult rv;
492 :
493 : // Copy the data into a nsCString
494 168 : nsCString chunk;
495 84 : rv = NS_ConsumeStream(aIStream, aLength, chunk);
496 84 : NS_ENSURE_SUCCESS(rv, rv);
497 :
498 : //LOG(("Chunk (%d): %s\n\n", chunk.Length(), chunk.get()));
499 :
500 84 : rv = mDBService->UpdateStream(chunk);
501 84 : NS_ENSURE_SUCCESS(rv, rv);
502 :
503 84 : return NS_OK;
504 : }
505 :
506 : NS_IMETHODIMP
507 86 : nsUrlClassifierStreamUpdater::OnStopRequest(nsIRequest *request, nsISupports* context,
508 : nsresult aStatus)
509 : {
510 86 : if (!mDBService)
511 0 : return NS_ERROR_NOT_INITIALIZED;
512 :
513 86 : LOG(("OnStopRequest (status %x)", aStatus));
514 :
515 : nsresult rv;
516 :
517 86 : if (NS_SUCCEEDED(aStatus)) {
518 : // Success, finish this stream and move on to the next.
519 84 : rv = mDBService->FinishStream();
520 2 : } else if (mBeganStream) {
521 : // We began this stream and couldn't finish it. We have to cancel the
522 : // update, it's not in a consistent state.
523 0 : rv = mDBService->CancelUpdate();
524 : } else {
525 : // The fetch failed, but we didn't start the stream (probably a
526 : // server or connection error). We can commit what we've applied
527 : // so far, and request again later.
528 2 : rv = mDBService->FinishUpdate();
529 : }
530 :
531 86 : mChannel = nsnull;
532 :
533 86 : return rv;
534 : }
535 :
536 : ///////////////////////////////////////////////////////////////////////////////
537 : // nsIObserver implementation
538 :
539 : NS_IMETHODIMP
540 0 : nsUrlClassifierStreamUpdater::Observe(nsISupports *aSubject, const char *aTopic,
541 : const PRUnichar *aData)
542 : {
543 0 : if (nsCRT::strcmp(aTopic, gQuitApplicationMessage) == 0) {
544 0 : if (mIsUpdating && mChannel) {
545 0 : LOG(("Cancel download"));
546 : nsresult rv;
547 0 : rv = mChannel->Cancel(NS_ERROR_ABORT);
548 0 : NS_ENSURE_SUCCESS(rv, rv);
549 0 : mIsUpdating = false;
550 0 : mChannel = nsnull;
551 : }
552 0 : if (mTimer) {
553 0 : mTimer->Cancel();
554 0 : mTimer = nsnull;
555 : }
556 : }
557 0 : return NS_OK;
558 : }
559 :
560 : ///////////////////////////////////////////////////////////////////////////////
561 : // nsIBadCertListener2 implementation
562 :
563 : NS_IMETHODIMP
564 0 : nsUrlClassifierStreamUpdater::NotifyCertProblem(nsIInterfaceRequestor *socketInfo,
565 : nsISSLStatus *status,
566 : const nsACString &targetSite,
567 : bool *_retval)
568 : {
569 0 : *_retval = true;
570 0 : return NS_OK;
571 : }
572 :
573 : ///////////////////////////////////////////////////////////////////////////////
574 : // nsISSLErrorListener implementation
575 :
576 : NS_IMETHODIMP
577 0 : nsUrlClassifierStreamUpdater::NotifySSLError(nsIInterfaceRequestor *socketInfo,
578 : PRInt32 error,
579 : const nsACString &targetSite,
580 : bool *_retval)
581 : {
582 0 : *_retval = true;
583 0 : return NS_OK;
584 : }
585 :
586 : ///////////////////////////////////////////////////////////////////////////////
587 : // nsIInterfaceRequestor implementation
588 :
589 : NS_IMETHODIMP
590 4 : nsUrlClassifierStreamUpdater::GetInterface(const nsIID & eventSinkIID, void* *_retval)
591 : {
592 4 : return QueryInterface(eventSinkIID, _retval);
593 : }
594 :
595 :
596 : ///////////////////////////////////////////////////////////////////////////////
597 : // nsITimerCallback implementation
598 : NS_IMETHODIMP
599 14 : nsUrlClassifierStreamUpdater::Notify(nsITimer *timer)
600 : {
601 14 : LOG(("nsUrlClassifierStreamUpdater::Notify [%p]", this));
602 :
603 14 : mTimer = nsnull;
604 :
605 : // Start the update process up again.
606 14 : FetchNext();
607 :
608 14 : return NS_OK;
609 : }
610 :
|