1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim:set ts=4 sw=4 cindent et: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Prasad Sunkari <prasad@medhas.org>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsIOService.h"
41 : #include "nsIProtocolHandler.h"
42 : #include "nsIFileProtocolHandler.h"
43 : #include "nscore.h"
44 : #include "nsIServiceManager.h"
45 : #include "nsIURI.h"
46 : #include "nsIStreamListener.h"
47 : #include "prprf.h"
48 : #include "prlog.h"
49 : #include "nsLoadGroup.h"
50 : #include "nsInputStreamChannel.h"
51 : #include "nsXPIDLString.h"
52 : #include "nsReadableUtils.h"
53 : #include "nsIErrorService.h"
54 : #include "netCore.h"
55 : #include "nsIObserverService.h"
56 : #include "nsIPrefService.h"
57 : #include "nsIPrefLocalizedString.h"
58 : #include "nsICategoryManager.h"
59 : #include "nsXPCOM.h"
60 : #include "nsISupportsPrimitives.h"
61 : #include "nsIProxiedProtocolHandler.h"
62 : #include "nsIProxyInfo.h"
63 : #include "nsEscape.h"
64 : #include "nsNetCID.h"
65 : #include "nsISocketTransport.h"
66 : #include "nsCRT.h"
67 : #include "nsSimpleNestedURI.h"
68 : #include "nsNetUtil.h"
69 : #include "nsThreadUtils.h"
70 : #include "nsIPermissionManager.h"
71 : #include "nsTArray.h"
72 : #include "nsIConsoleService.h"
73 : #include "nsIUploadChannel2.h"
74 : #include "nsXULAppAPI.h"
75 :
76 : #include "mozilla/FunctionTimer.h"
77 :
78 : #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
79 : #include "nsNativeConnectionHelper.h"
80 : #endif
81 :
82 : #define PORT_PREF_PREFIX "network.security.ports."
83 : #define PORT_PREF(x) PORT_PREF_PREFIX x
84 : #define AUTODIAL_PREF "network.autodial-helper.enabled"
85 : #define MANAGE_OFFLINE_STATUS_PREF "network.manage-offline-status"
86 :
87 : // Nb: these have been misnomers since bug 715770 removed the buffer cache.
88 : // "network.segment.count" and "network.segment.size" would be better names,
89 : // but the old names are still used to preserve backward compatibility.
90 : #define NECKO_BUFFER_CACHE_COUNT_PREF "network.buffer.cache.count"
91 : #define NECKO_BUFFER_CACHE_SIZE_PREF "network.buffer.cache.size"
92 :
93 : #define MAX_RECURSION_COUNT 50
94 :
95 : nsIOService* gIOService = nsnull;
96 : static bool gHasWarnedUploadChannel2;
97 :
98 : // A general port blacklist. Connections to these ports will not be allowed unless
99 : // the protocol overrides.
100 : //
101 : // TODO: I am sure that there are more ports to be added.
102 : // This cut is based on the classic mozilla codebase
103 :
104 : PRInt16 gBadPortList[] = {
105 : 1, // tcpmux
106 : 7, // echo
107 : 9, // discard
108 : 11, // systat
109 : 13, // daytime
110 : 15, // netstat
111 : 17, // qotd
112 : 19, // chargen
113 : 20, // ftp-data
114 : 21, // ftp-cntl
115 : 22, // ssh
116 : 23, // telnet
117 : 25, // smtp
118 : 37, // time
119 : 42, // name
120 : 43, // nicname
121 : 53, // domain
122 : 77, // priv-rjs
123 : 79, // finger
124 : 87, // ttylink
125 : 95, // supdup
126 : 101, // hostriame
127 : 102, // iso-tsap
128 : 103, // gppitnp
129 : 104, // acr-nema
130 : 109, // pop2
131 : 110, // pop3
132 : 111, // sunrpc
133 : 113, // auth
134 : 115, // sftp
135 : 117, // uucp-path
136 : 119, // nntp
137 : 123, // NTP
138 : 135, // loc-srv / epmap
139 : 139, // netbios
140 : 143, // imap2
141 : 179, // BGP
142 : 389, // ldap
143 : 465, // smtp+ssl
144 : 512, // print / exec
145 : 513, // login
146 : 514, // shell
147 : 515, // printer
148 : 526, // tempo
149 : 530, // courier
150 : 531, // Chat
151 : 532, // netnews
152 : 540, // uucp
153 : 556, // remotefs
154 : 563, // nntp+ssl
155 : 587, //
156 : 601, //
157 : 636, // ldap+ssl
158 : 993, // imap+ssl
159 : 995, // pop3+ssl
160 : 2049, // nfs
161 : 4045, // lockd
162 : 6000, // x11
163 : 0, // This MUST be zero so that we can populating the array
164 : };
165 :
166 : static const char kProfileChangeNetTeardownTopic[] = "profile-change-net-teardown";
167 : static const char kProfileChangeNetRestoreTopic[] = "profile-change-net-restore";
168 : static const char kProfileDoChange[] = "profile-do-change";
169 :
170 : // Necko buffer defaults
171 : PRUint32 nsIOService::gDefaultSegmentSize = 4096;
172 : PRUint32 nsIOService::gDefaultSegmentCount = 24;
173 :
174 : ////////////////////////////////////////////////////////////////////////////////
175 :
176 1419 : nsIOService::nsIOService()
177 : : mOffline(true)
178 : , mOfflineForProfileChange(false)
179 : , mManageOfflineStatus(false)
180 : , mSettingOffline(false)
181 : , mSetOfflineValue(false)
182 : , mShutdown(false)
183 : , mNetworkLinkServiceInitialized(false)
184 : , mChannelEventSinks(NS_CHANNEL_EVENT_SINK_CATEGORY)
185 : , mContentSniffers(NS_CONTENT_SNIFFER_CATEGORY)
186 1419 : , mAutoDialEnabled(false)
187 : {
188 1419 : }
189 :
190 : nsresult
191 1419 : nsIOService::Init()
192 : {
193 : NS_TIME_FUNCTION;
194 :
195 : nsresult rv;
196 :
197 : // We need to get references to the DNS service so that we can shut it
198 : // down later. If we wait until the nsIOService is being shut down,
199 : // GetService will fail at that point.
200 :
201 1419 : mDNSService = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
202 1419 : if (NS_FAILED(rv)) {
203 0 : NS_WARNING("failed to get DNS service");
204 0 : return rv;
205 : }
206 :
207 : NS_TIME_FUNCTION_MARK("got DNS Service");
208 :
209 : // XXX hack until xpidl supports error info directly (bug 13423)
210 2838 : nsCOMPtr<nsIErrorService> errorService = do_GetService(NS_ERRORSERVICE_CONTRACTID);
211 1419 : if (errorService) {
212 1419 : errorService->RegisterErrorStringBundle(NS_ERROR_MODULE_NETWORK, NECKO_MSGS_URL);
213 : }
214 : else
215 0 : NS_WARNING("failed to get error service");
216 :
217 : NS_TIME_FUNCTION_MARK("got Error Service");
218 :
219 : // setup our bad port list stuff
220 83721 : for(int i=0; gBadPortList[i]; i++)
221 82302 : mRestrictedPortList.AppendElement(gBadPortList[i]);
222 :
223 : // Further modifications to the port list come from prefs
224 2838 : nsCOMPtr<nsIPrefBranch> prefBranch;
225 1419 : GetPrefBranch(getter_AddRefs(prefBranch));
226 1419 : if (prefBranch) {
227 1419 : prefBranch->AddObserver(PORT_PREF_PREFIX, this, true);
228 1419 : prefBranch->AddObserver(AUTODIAL_PREF, this, true);
229 1419 : prefBranch->AddObserver(MANAGE_OFFLINE_STATUS_PREF, this, true);
230 1419 : PrefsChanged(prefBranch);
231 : }
232 :
233 : // Register for profile change notifications
234 : nsCOMPtr<nsIObserverService> observerService =
235 2838 : mozilla::services::GetObserverService();
236 1419 : if (observerService) {
237 1419 : observerService->AddObserver(this, kProfileChangeNetTeardownTopic, true);
238 1419 : observerService->AddObserver(this, kProfileChangeNetRestoreTopic, true);
239 1419 : observerService->AddObserver(this, kProfileDoChange, true);
240 1419 : observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, true);
241 1419 : observerService->AddObserver(this, NS_NETWORK_LINK_TOPIC, true);
242 : }
243 : else
244 0 : NS_WARNING("failed to get observer service");
245 :
246 : NS_TIME_FUNCTION_MARK("Registered observers");
247 :
248 1419 : gIOService = this;
249 :
250 1419 : InitializeNetworkLinkService();
251 :
252 : NS_TIME_FUNCTION_MARK("Set up network link service");
253 :
254 1419 : return NS_OK;
255 : }
256 :
257 :
258 12744 : nsIOService::~nsIOService()
259 : {
260 1416 : gIOService = nsnull;
261 11328 : }
262 :
263 : nsresult
264 1426 : nsIOService::InitializeSocketTransportService()
265 : {
266 : NS_TIME_FUNCTION;
267 :
268 1426 : nsresult rv = NS_OK;
269 :
270 1426 : if (!mSocketTransportService) {
271 1419 : mSocketTransportService = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
272 1419 : if (NS_FAILED(rv)) {
273 0 : NS_WARNING("failed to get socket transport service");
274 : }
275 : }
276 :
277 1426 : if (mSocketTransportService) {
278 1426 : rv = mSocketTransportService->Init();
279 1426 : NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service init failed");
280 1426 : mSocketTransportService->SetAutodialEnabled(mAutoDialEnabled);
281 : }
282 :
283 1426 : return rv;
284 : }
285 :
286 : nsresult
287 4225 : nsIOService::InitializeNetworkLinkService()
288 : {
289 : NS_TIME_FUNCTION;
290 :
291 4225 : nsresult rv = NS_OK;
292 :
293 4225 : if (mNetworkLinkServiceInitialized)
294 1 : return rv;
295 :
296 4224 : if (!NS_IsMainThread()) {
297 0 : NS_WARNING("Network link service should be created on main thread");
298 0 : return NS_ERROR_FAILURE;
299 : }
300 :
301 : // go into managed mode if we can, and chrome process
302 4224 : if (XRE_GetProcessType() == GeckoProcessType_Default)
303 : {
304 4224 : mNetworkLinkService = do_GetService(NS_NETWORK_LINK_SERVICE_CONTRACTID, &rv);
305 : }
306 :
307 4224 : if (mNetworkLinkService) {
308 1386 : mNetworkLinkServiceInitialized = true;
309 : }
310 : else {
311 : // We can't really determine if the machine has a usable network connection,
312 : // so let's cross our fingers!
313 2838 : mManageOfflineStatus = false;
314 : }
315 :
316 :
317 4224 : if (mManageOfflineStatus)
318 0 : TrackNetworkLinkStatusForOffline();
319 : else
320 4224 : SetOffline(false);
321 :
322 4224 : return rv;
323 : }
324 :
325 : nsIOService*
326 1465 : nsIOService::GetInstance() {
327 1465 : if (!gIOService) {
328 1419 : gIOService = new nsIOService();
329 1419 : if (!gIOService)
330 0 : return nsnull;
331 1419 : NS_ADDREF(gIOService);
332 :
333 1419 : nsresult rv = gIOService->Init();
334 1419 : if (NS_FAILED(rv)) {
335 0 : NS_RELEASE(gIOService);
336 0 : return nsnull;
337 : }
338 1419 : return gIOService;
339 : }
340 46 : NS_ADDREF(gIOService);
341 46 : return gIOService;
342 : }
343 :
344 2587249 : NS_IMPL_THREADSAFE_ISUPPORTS5(nsIOService,
345 : nsIIOService,
346 : nsIIOService2,
347 : nsINetUtil,
348 : nsIObserver,
349 : nsISupportsWeakReference)
350 :
351 : ////////////////////////////////////////////////////////////////////////////////
352 :
353 : nsresult
354 155 : nsIOService::AsyncOnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan,
355 : PRUint32 flags,
356 : nsAsyncRedirectVerifyHelper *helper)
357 : {
358 : nsCOMPtr<nsIChannelEventSink> sink =
359 310 : do_GetService(NS_GLOBAL_CHANNELEVENTSINK_CONTRACTID);
360 155 : if (sink) {
361 : nsresult rv = helper->DelegateOnChannelRedirect(sink, oldChan,
362 155 : newChan, flags);
363 155 : if (NS_FAILED(rv))
364 2 : return rv;
365 : }
366 :
367 : // Finally, our category
368 : const nsCOMArray<nsIChannelEventSink>& entries =
369 153 : mChannelEventSinks.GetEntries();
370 153 : PRInt32 len = entries.Count();
371 306 : for (PRInt32 i = 0; i < len; ++i) {
372 : nsresult rv = helper->DelegateOnChannelRedirect(entries[i], oldChan,
373 154 : newChan, flags);
374 154 : if (NS_FAILED(rv))
375 1 : return rv;
376 : }
377 152 : return NS_OK;
378 : }
379 :
380 : nsresult
381 11798 : nsIOService::CacheProtocolHandler(const char *scheme, nsIProtocolHandler *handler)
382 : {
383 54323 : for (unsigned int i=0; i<NS_N(gScheme); i++)
384 : {
385 47587 : if (!nsCRT::strcasecmp(scheme, gScheme[i]))
386 : {
387 : nsresult rv;
388 5062 : NS_ASSERTION(!mWeakHandler[i], "Protocol handler already cached");
389 : // Make sure the handler supports weak references.
390 10124 : nsCOMPtr<nsISupportsWeakReference> factoryPtr = do_QueryInterface(handler, &rv);
391 5062 : if (!factoryPtr)
392 : {
393 : // Don't cache handlers that don't support weak reference as
394 : // there is real danger of a circular reference.
395 : #ifdef DEBUG_dp
396 : printf("DEBUG: %s protcol handler doesn't support weak ref. Not cached.\n", scheme);
397 : #endif /* DEBUG_dp */
398 0 : return NS_ERROR_FAILURE;
399 : }
400 5062 : mWeakHandler[i] = do_GetWeakReference(handler);
401 5062 : return NS_OK;
402 : }
403 : }
404 6736 : return NS_ERROR_FAILURE;
405 : }
406 :
407 : nsresult
408 533538 : nsIOService::GetCachedProtocolHandler(const char *scheme, nsIProtocolHandler **result, PRUint32 start, PRUint32 end)
409 : {
410 533538 : PRUint32 len = end - start - 1;
411 1458779 : for (unsigned int i=0; i<NS_N(gScheme); i++)
412 : {
413 1446722 : if (!mWeakHandler[i])
414 192926 : continue;
415 :
416 : // handle unterminated strings
417 : // start is inclusive, end is exclusive, len = end - start - 1
418 2507592 : if (end ? (!nsCRT::strncasecmp(scheme + start, gScheme[i], len)
419 0 : && gScheme[i][len] == '\0')
420 1253796 : : (!nsCRT::strcasecmp(scheme, gScheme[i])))
421 : {
422 521481 : return CallQueryReferent(mWeakHandler[i].get(), result);
423 : }
424 : }
425 12057 : return NS_ERROR_FAILURE;
426 : }
427 :
428 : NS_IMETHODIMP
429 533538 : nsIOService::GetProtocolHandler(const char* scheme, nsIProtocolHandler* *result)
430 : {
431 : nsresult rv;
432 :
433 533538 : NS_ENSURE_ARG_POINTER(scheme);
434 : // XXX we may want to speed this up by introducing our own protocol
435 : // scheme -> protocol handler mapping, avoiding the string manipulation
436 : // and service manager stuff
437 :
438 533538 : rv = GetCachedProtocolHandler(scheme, result);
439 533538 : if (NS_SUCCEEDED(rv))
440 521481 : return rv;
441 :
442 12057 : bool externalProtocol = false;
443 24114 : nsCOMPtr<nsIPrefBranch> prefBranch;
444 12057 : GetPrefBranch(getter_AddRefs(prefBranch));
445 12057 : if (prefBranch) {
446 24114 : nsCAutoString externalProtocolPref("network.protocol-handler.external.");
447 12057 : externalProtocolPref += scheme;
448 12057 : rv = prefBranch->GetBoolPref(externalProtocolPref.get(), &externalProtocol);
449 12057 : if (NS_FAILED(rv)) {
450 7712 : externalProtocol = false;
451 : }
452 : }
453 :
454 12057 : if (!externalProtocol) {
455 24014 : nsCAutoString contractID(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX);
456 12007 : contractID += scheme;
457 12007 : ToLowerCase(contractID);
458 :
459 12007 : rv = CallGetService(contractID.get(), result);
460 12007 : if (NS_SUCCEEDED(rv)) {
461 11798 : CacheProtocolHandler(scheme, *result);
462 11798 : return rv;
463 : }
464 :
465 : #ifdef MOZ_X11
466 : // check to see whether GVFS can handle this URI scheme. if it can
467 : // create a nsIURI for the "scheme:", then we assume it has support for
468 : // the requested protocol. otherwise, we failover to using the default
469 : // protocol handler.
470 :
471 : rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"moz-gio",
472 209 : result);
473 209 : if (NS_SUCCEEDED(rv)) {
474 0 : nsCAutoString spec(scheme);
475 0 : spec.Append(':');
476 :
477 : nsIURI *uri;
478 0 : rv = (*result)->NewURI(spec, nsnull, nsnull, &uri);
479 0 : if (NS_SUCCEEDED(rv)) {
480 0 : NS_RELEASE(uri);
481 0 : return rv;
482 : }
483 :
484 0 : NS_RELEASE(*result);
485 : }
486 :
487 : // check to see whether GnomeVFS can handle this URI scheme. if it can
488 : // create a nsIURI for the "scheme:", then we assume it has support for
489 : // the requested protocol. otherwise, we failover to using the default
490 : // protocol handler.
491 :
492 : // XXX should this be generalized into something that searches a
493 : // category? (see bug 234714)
494 :
495 : rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"moz-gnomevfs",
496 209 : result);
497 209 : if (NS_SUCCEEDED(rv)) {
498 418 : nsCAutoString spec(scheme);
499 209 : spec.Append(':');
500 :
501 : nsIURI *uri;
502 209 : rv = (*result)->NewURI(spec, nsnull, nsnull, &uri);
503 209 : if (NS_SUCCEEDED(rv)) {
504 0 : NS_RELEASE(uri);
505 0 : return rv;
506 : }
507 :
508 418 : NS_RELEASE(*result);
509 : }
510 : #endif
511 : }
512 :
513 : // Okay we don't have a protocol handler to handle this url type, so use
514 : // the default protocol handler. This will cause urls to get dispatched
515 : // out to the OS ('cause we can't do anything with them) when we try to
516 : // read from a channel created by the default protocol handler.
517 :
518 : rv = CallGetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX"default",
519 259 : result);
520 259 : if (NS_FAILED(rv))
521 0 : return NS_ERROR_UNKNOWN_PROTOCOL;
522 :
523 259 : return rv;
524 : }
525 :
526 : NS_IMETHODIMP
527 283251 : nsIOService::ExtractScheme(const nsACString &inURI, nsACString &scheme)
528 : {
529 283251 : return net_ExtractURLScheme(inURI, nsnull, nsnull, &scheme);
530 : }
531 :
532 : NS_IMETHODIMP
533 105049 : nsIOService::GetProtocolFlags(const char* scheme, PRUint32 *flags)
534 : {
535 210098 : nsCOMPtr<nsIProtocolHandler> handler;
536 105049 : nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
537 105049 : if (NS_FAILED(rv)) return rv;
538 :
539 105049 : rv = handler->GetProtocolFlags(flags);
540 105049 : return rv;
541 : }
542 :
543 : class AutoIncrement
544 : {
545 : public:
546 281091 : AutoIncrement(PRUint32 *var) : mVar(var)
547 : {
548 281091 : ++*var;
549 281091 : }
550 281091 : ~AutoIncrement()
551 : {
552 281091 : --*mVar;
553 281091 : }
554 : private:
555 : PRUint32 *mVar;
556 : };
557 :
558 : nsresult
559 281092 : nsIOService::NewURI(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI, nsIURI **result)
560 : {
561 281092 : NS_ASSERTION(NS_IsMainThread(), "wrong thread");
562 :
563 : static PRUint32 recursionCount = 0;
564 281092 : if (recursionCount >= MAX_RECURSION_COUNT)
565 1 : return NS_ERROR_MALFORMED_URI;
566 562182 : AutoIncrement inc(&recursionCount);
567 :
568 562182 : nsCAutoString scheme;
569 281091 : nsresult rv = ExtractScheme(aSpec, scheme);
570 281091 : if (NS_FAILED(rv)) {
571 : // then aSpec is relative
572 63077 : if (!aBaseURI)
573 324 : return NS_ERROR_MALFORMED_URI;
574 :
575 62753 : rv = aBaseURI->GetScheme(scheme);
576 62753 : if (NS_FAILED(rv)) return rv;
577 : }
578 :
579 : // now get the handler for this scheme
580 561534 : nsCOMPtr<nsIProtocolHandler> handler;
581 280767 : rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
582 280767 : if (NS_FAILED(rv)) return rv;
583 :
584 280767 : return handler->NewURI(aSpec, aCharset, aBaseURI, result);
585 : }
586 :
587 :
588 : NS_IMETHODIMP
589 6324 : nsIOService::NewFileURI(nsIFile *file, nsIURI **result)
590 : {
591 : nsresult rv;
592 6324 : NS_ENSURE_ARG_POINTER(file);
593 :
594 12648 : nsCOMPtr<nsIProtocolHandler> handler;
595 :
596 6324 : rv = GetProtocolHandler("file", getter_AddRefs(handler));
597 6324 : if (NS_FAILED(rv)) return rv;
598 :
599 12648 : nsCOMPtr<nsIFileProtocolHandler> fileHandler( do_QueryInterface(handler, &rv) );
600 6324 : if (NS_FAILED(rv)) return rv;
601 :
602 6324 : return fileHandler->NewFileURI(file, result);
603 : }
604 :
605 : NS_IMETHODIMP
606 104361 : nsIOService::NewChannelFromURI(nsIURI *aURI, nsIChannel **result)
607 : {
608 104361 : return NewChannelFromURIWithProxyFlags(aURI, nsnull, 0, result);
609 : }
610 :
611 : NS_IMETHODIMP
612 104361 : nsIOService::NewChannelFromURIWithProxyFlags(nsIURI *aURI,
613 : nsIURI *aProxyURI,
614 : PRUint32 proxyFlags,
615 : nsIChannel **result)
616 : {
617 : nsresult rv;
618 104361 : NS_ENSURE_ARG_POINTER(aURI);
619 :
620 208722 : nsCAutoString scheme;
621 104361 : rv = aURI->GetScheme(scheme);
622 104361 : if (NS_FAILED(rv))
623 0 : return rv;
624 :
625 208722 : nsCOMPtr<nsIProtocolHandler> handler;
626 104361 : rv = GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
627 104361 : if (NS_FAILED(rv))
628 0 : return rv;
629 :
630 : PRUint32 protoFlags;
631 104361 : rv = handler->GetProtocolFlags(&protoFlags);
632 104361 : if (NS_FAILED(rv))
633 0 : return rv;
634 :
635 : // Talk to the PPS if the protocol handler allows proxying. Otherwise,
636 : // skip this step. This allows us to lazily load the PPS at startup.
637 104361 : if (protoFlags & nsIProtocolHandler::ALLOWS_PROXY) {
638 7030 : nsCOMPtr<nsIProxyInfo> pi;
639 3515 : if (!mProxyService) {
640 277 : mProxyService = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
641 277 : if (!mProxyService)
642 0 : NS_WARNING("failed to get protocol proxy service");
643 : }
644 3515 : if (mProxyService) {
645 3515 : PRUint32 flags = 0;
646 3515 : if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))
647 3493 : flags = nsIProtocolProxyService::RESOLVE_NON_BLOCKING;
648 3515 : rv = mProxyService->Resolve(aProxyURI ? aProxyURI : aURI, proxyFlags,
649 3515 : getter_AddRefs(pi));
650 3515 : if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
651 : // Use an UNKNOWN proxy to defer resolution and avoid blocking.
652 0 : rv = mProxyService->NewProxyInfo(NS_LITERAL_CSTRING("unknown"),
653 0 : NS_LITERAL_CSTRING(""),
654 : -1, 0, 0, nsnull,
655 0 : getter_AddRefs(pi));
656 : }
657 3515 : if (NS_FAILED(rv))
658 0 : pi = nsnull;
659 : }
660 3515 : if (pi) {
661 34 : nsCAutoString type;
662 17 : if (NS_SUCCEEDED(pi->GetType(type)) && type.EqualsLiteral("http")) {
663 : // we are going to proxy this channel using an http proxy
664 7 : rv = GetProtocolHandler("http", getter_AddRefs(handler));
665 7 : if (NS_FAILED(rv))
666 0 : return rv;
667 : }
668 34 : nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler);
669 17 : if (pph)
670 17 : return pph->NewProxiedChannel(aURI, pi, result);
671 : }
672 : }
673 :
674 104344 : rv = handler->NewChannel(aURI, result);
675 104344 : NS_ENSURE_SUCCESS(rv, rv);
676 :
677 : // Some extensions override the http protocol handler and provide their own
678 : // implementation. The channels returned from that implementation doesn't
679 : // seem to always implement the nsIUploadChannel2 interface, presumably
680 : // because it's a new interface.
681 : // Eventually we should remove this and simply require that http channels
682 : // implement the new interface.
683 : // See bug 529041
684 103452 : if (!gHasWarnedUploadChannel2 && scheme.EqualsLiteral("http")) {
685 6942 : nsCOMPtr<nsIUploadChannel2> uploadChannel2 = do_QueryInterface(*result);
686 3471 : if (!uploadChannel2) {
687 : nsCOMPtr<nsIConsoleService> consoleService =
688 0 : do_GetService(NS_CONSOLESERVICE_CONTRACTID);
689 0 : if (consoleService) {
690 0 : consoleService->LogStringMessage(NS_LITERAL_STRING(
691 : "Http channel implementation doesn't support nsIUploadChannel2. An extension has supplied a non-functional http protocol handler. This will break behavior and in future releases not work at all."
692 0 : ).get());
693 : }
694 0 : gHasWarnedUploadChannel2 = true;
695 : }
696 : }
697 :
698 103452 : return NS_OK;
699 : }
700 :
701 : NS_IMETHODIMP
702 50575 : nsIOService::NewChannel(const nsACString &aSpec, const char *aCharset, nsIURI *aBaseURI, nsIChannel **result)
703 : {
704 : nsresult rv;
705 101150 : nsCOMPtr<nsIURI> uri;
706 50575 : rv = NewURI(aSpec, aCharset, aBaseURI, getter_AddRefs(uri));
707 50575 : if (NS_FAILED(rv)) return rv;
708 :
709 50574 : return NewChannelFromURI(uri, result);
710 : }
711 :
712 : bool
713 0 : nsIOService::IsLinkUp()
714 : {
715 0 : InitializeNetworkLinkService();
716 :
717 0 : if (!mNetworkLinkService) {
718 : // We cannot decide, assume the link is up
719 0 : return true;
720 : }
721 :
722 : bool isLinkUp;
723 : nsresult rv;
724 0 : rv = mNetworkLinkService->GetIsLinkUp(&isLinkUp);
725 0 : if (NS_FAILED(rv)) {
726 0 : return true;
727 : }
728 :
729 0 : return isLinkUp;
730 : }
731 :
732 : NS_IMETHODIMP
733 8293 : nsIOService::GetOffline(bool *offline)
734 : {
735 8293 : *offline = mOffline;
736 8293 : return NS_OK;
737 : }
738 :
739 : NS_IMETHODIMP
740 7853 : nsIOService::SetOffline(bool offline)
741 : {
742 : // When someone wants to go online (!offline) after we got XPCOM shutdown
743 : // throw ERROR_NOT_AVAILABLE to prevent return to online state.
744 7853 : if (mShutdown && !offline)
745 0 : return NS_ERROR_NOT_AVAILABLE;
746 :
747 : // SetOffline() may re-enter while it's shutting down services.
748 : // If that happens, save the most recent value and it will be
749 : // processed when the first SetOffline() call is done bringing
750 : // down the service.
751 7853 : mSetOfflineValue = offline;
752 7853 : if (mSettingOffline) {
753 0 : return NS_OK;
754 : }
755 :
756 7853 : mSettingOffline = true;
757 :
758 : nsCOMPtr<nsIObserverService> observerService =
759 15706 : mozilla::services::GetObserverService();
760 :
761 7853 : NS_ASSERTION(observerService, "The observer service should not be null");
762 :
763 7853 : if (XRE_GetProcessType() == GeckoProcessType_Default) {
764 7853 : if (observerService) {
765 7853 : (void)observerService->NotifyObservers(nsnull,
766 : NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, offline ?
767 10087 : NS_LITERAL_STRING("true").get() :
768 10087 : NS_LITERAL_STRING("false").get());
769 : }
770 : }
771 :
772 18558 : while (mSetOfflineValue != mOffline) {
773 2852 : offline = mSetOfflineValue;
774 :
775 : nsresult rv;
776 2852 : if (offline && !mOffline) {
777 2852 : NS_NAMED_LITERAL_STRING(offlineString, NS_IOSERVICE_OFFLINE);
778 1426 : mOffline = true; // indicate we're trying to shutdown
779 :
780 : // don't care if notification fails
781 : // this allows users to attempt a little cleanup before dns and socket transport are shut down.
782 1426 : if (observerService)
783 1426 : observerService->NotifyObservers(static_cast<nsIIOService *>(this),
784 : NS_IOSERVICE_GOING_OFFLINE_TOPIC,
785 1426 : offlineString.get());
786 :
787 : // be sure to try and shutdown both (even if the first fails)...
788 : // shutdown dns service first, because it has callbacks for socket transport
789 1426 : if (mDNSService) {
790 1426 : rv = mDNSService->Shutdown();
791 1426 : NS_ASSERTION(NS_SUCCEEDED(rv), "DNS service shutdown failed");
792 : }
793 1426 : if (mSocketTransportService) {
794 1426 : rv = mSocketTransportService->Shutdown();
795 1426 : NS_ASSERTION(NS_SUCCEEDED(rv), "socket transport service shutdown failed");
796 : }
797 :
798 : // don't care if notification fails
799 1426 : if (observerService)
800 1426 : observerService->NotifyObservers(static_cast<nsIIOService *>(this),
801 : NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
802 2852 : offlineString.get());
803 : }
804 1426 : else if (!offline && mOffline) {
805 : // go online
806 1426 : if (mDNSService) {
807 1426 : rv = mDNSService->Init();
808 1426 : NS_ASSERTION(NS_SUCCEEDED(rv), "DNS service init failed");
809 : }
810 1426 : InitializeSocketTransportService();
811 1426 : mOffline = false; // indicate success only AFTER we've
812 : // brought up the services
813 :
814 : // trigger a PAC reload when we come back online
815 1426 : if (mProxyService)
816 6 : mProxyService->ReloadPAC();
817 :
818 : // don't care if notification fails
819 1426 : if (observerService)
820 1426 : observerService->NotifyObservers(static_cast<nsIIOService *>(this),
821 : NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
822 1426 : NS_LITERAL_STRING(NS_IOSERVICE_ONLINE).get());
823 : }
824 : }
825 :
826 7853 : mSettingOffline = false;
827 :
828 7853 : return NS_OK;
829 : }
830 :
831 :
832 : NS_IMETHODIMP
833 3125 : nsIOService::AllowPort(PRInt32 inPort, const char *scheme, bool *_retval)
834 : {
835 3125 : PRInt16 port = inPort;
836 3125 : if (port == -1) {
837 0 : *_retval = true;
838 0 : return NS_OK;
839 : }
840 :
841 : // first check to see if the port is in our blacklist:
842 3125 : PRInt32 badPortListCnt = mRestrictedPortList.Length();
843 184375 : for (int i=0; i<badPortListCnt; i++)
844 : {
845 181250 : if (port == mRestrictedPortList[i])
846 : {
847 0 : *_retval = false;
848 :
849 : // check to see if the protocol wants to override
850 0 : if (!scheme)
851 0 : return NS_OK;
852 :
853 0 : nsCOMPtr<nsIProtocolHandler> handler;
854 0 : nsresult rv = GetProtocolHandler(scheme, getter_AddRefs(handler));
855 0 : if (NS_FAILED(rv)) return rv;
856 :
857 : // let the protocol handler decide
858 0 : return handler->AllowPort(port, scheme, _retval);
859 : }
860 : }
861 :
862 3125 : *_retval = true;
863 3125 : return NS_OK;
864 : }
865 :
866 : ////////////////////////////////////////////////////////////////////////////////
867 :
868 : void
869 1420 : nsIOService::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
870 : {
871 1420 : if (!prefs) return;
872 :
873 : // Look for extra ports to block
874 1420 : if (!pref || strcmp(pref, PORT_PREF("banned")) == 0)
875 1419 : ParsePortList(prefs, PORT_PREF("banned"), false);
876 :
877 : // ...as well as previous blocks to remove.
878 1420 : if (!pref || strcmp(pref, PORT_PREF("banned.override")) == 0)
879 1419 : ParsePortList(prefs, PORT_PREF("banned.override"), true);
880 :
881 1420 : if (!pref || strcmp(pref, AUTODIAL_PREF) == 0) {
882 1419 : bool enableAutodial = false;
883 1419 : nsresult rv = prefs->GetBoolPref(AUTODIAL_PREF, &enableAutodial);
884 : // If pref not found, default to disabled.
885 1419 : mAutoDialEnabled = enableAutodial;
886 1419 : if (NS_SUCCEEDED(rv)) {
887 0 : if (mSocketTransportService)
888 0 : mSocketTransportService->SetAutodialEnabled(enableAutodial);
889 : }
890 : }
891 :
892 1420 : if (!pref || strcmp(pref, MANAGE_OFFLINE_STATUS_PREF) == 0) {
893 : bool manage;
894 1420 : if (NS_SUCCEEDED(prefs->GetBoolPref(MANAGE_OFFLINE_STATUS_PREF,
895 : &manage)))
896 1420 : SetManageOfflineStatus(manage);
897 : }
898 :
899 1420 : if (!pref || strcmp(pref, NECKO_BUFFER_CACHE_COUNT_PREF) == 0) {
900 : PRInt32 count;
901 1419 : if (NS_SUCCEEDED(prefs->GetIntPref(NECKO_BUFFER_CACHE_COUNT_PREF,
902 : &count)))
903 : /* check for bogus values and default if we find such a value */
904 1419 : if (count > 0)
905 1419 : gDefaultSegmentCount = count;
906 : }
907 :
908 1420 : if (!pref || strcmp(pref, NECKO_BUFFER_CACHE_SIZE_PREF) == 0) {
909 : PRInt32 size;
910 1419 : if (NS_SUCCEEDED(prefs->GetIntPref(NECKO_BUFFER_CACHE_SIZE_PREF,
911 : &size)))
912 : /* check for bogus values and default if we find such a value
913 : * the upper limit here is arbitrary. having a 1mb segment size
914 : * is pretty crazy. if you remove this, consider adding some
915 : * integer rollover test.
916 : */
917 1419 : if (size > 0 && size < 1024*1024)
918 1419 : gDefaultSegmentSize = size;
919 1419 : NS_WARN_IF_FALSE( (!(size & (size - 1))) , "network segment size is not a power of 2!");
920 : }
921 : }
922 :
923 : void
924 2838 : nsIOService::ParsePortList(nsIPrefBranch *prefBranch, const char *pref, bool remove)
925 : {
926 5676 : nsXPIDLCString portList;
927 :
928 : // Get a pref string and chop it up into a list of ports.
929 2838 : prefBranch->GetCharPref(pref, getter_Copies(portList));
930 2838 : if (portList) {
931 0 : nsTArray<nsCString> portListArray;
932 0 : ParseString(portList, ',', portListArray);
933 : PRUint32 index;
934 0 : for (index=0; index < portListArray.Length(); index++) {
935 0 : portListArray[index].StripWhitespace();
936 : PRInt32 aErrorCode, portBegin, portEnd;
937 :
938 0 : if (PR_sscanf(portListArray[index].get(), "%d-%d", &portBegin, &portEnd) == 2) {
939 0 : if ((portBegin < 65536) && (portEnd < 65536)) {
940 : PRInt32 curPort;
941 0 : if (remove) {
942 0 : for (curPort=portBegin; curPort <= portEnd; curPort++)
943 0 : mRestrictedPortList.RemoveElement(curPort);
944 : } else {
945 0 : for (curPort=portBegin; curPort <= portEnd; curPort++)
946 0 : mRestrictedPortList.AppendElement(curPort);
947 : }
948 : }
949 : } else {
950 0 : PRInt32 port = portListArray[index].ToInteger(&aErrorCode);
951 0 : if (NS_SUCCEEDED(aErrorCode) && port < 65536) {
952 0 : if (remove)
953 0 : mRestrictedPortList.RemoveElement(port);
954 : else
955 0 : mRestrictedPortList.AppendElement(port);
956 : }
957 : }
958 :
959 : }
960 : }
961 2838 : }
962 :
963 : void
964 13476 : nsIOService::GetPrefBranch(nsIPrefBranch **result)
965 : {
966 13476 : *result = nsnull;
967 13476 : CallGetService(NS_PREFSERVICE_CONTRACTID, result);
968 13476 : }
969 :
970 : // nsIObserver interface
971 : NS_IMETHODIMP
972 2234 : nsIOService::Observe(nsISupports *subject,
973 : const char *topic,
974 : const PRUnichar *data)
975 : {
976 2234 : if (!strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
977 2 : nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(subject);
978 1 : if (prefBranch)
979 1 : PrefsChanged(prefBranch, NS_ConvertUTF16toUTF8(data).get());
980 : }
981 2233 : else if (!strcmp(topic, kProfileChangeNetTeardownTopic)) {
982 814 : if (!mOffline) {
983 807 : SetOffline(true);
984 807 : mOfflineForProfileChange = true;
985 : }
986 : }
987 1419 : else if (!strcmp(topic, kProfileChangeNetRestoreTopic)) {
988 0 : if (mOfflineForProfileChange) {
989 0 : mOfflineForProfileChange = false;
990 0 : if (!mManageOfflineStatus ||
991 0 : NS_FAILED(TrackNetworkLinkStatusForOffline())) {
992 0 : SetOffline(false);
993 : }
994 : }
995 : }
996 1419 : else if (!strcmp(topic, kProfileDoChange)) {
997 0 : if (data && NS_LITERAL_STRING("startup").Equals(data)) {
998 : // Lazy initialization of network link service (see bug 620472)
999 0 : InitializeNetworkLinkService();
1000 : // Set up the initilization flag regardless the actuall result.
1001 : // If we fail here, we will fail always on.
1002 0 : mNetworkLinkServiceInitialized = true;
1003 : }
1004 : }
1005 1419 : else if (!strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
1006 : // Remember we passed XPCOM shutdown notification to prevent any
1007 : // changes of the offline status from now. We must not allow going
1008 : // online after this point.
1009 1419 : mShutdown = true;
1010 :
1011 1419 : SetOffline(true);
1012 :
1013 : // Break circular reference.
1014 1419 : mProxyService = nsnull;
1015 : }
1016 0 : else if (!strcmp(topic, NS_NETWORK_LINK_TOPIC)) {
1017 0 : if (!mOfflineForProfileChange && mManageOfflineStatus) {
1018 0 : TrackNetworkLinkStatusForOffline();
1019 : }
1020 : }
1021 :
1022 2234 : return NS_OK;
1023 : }
1024 :
1025 : // nsINetUtil interface
1026 : NS_IMETHODIMP
1027 128 : nsIOService::ParseContentType(const nsACString &aTypeHeader,
1028 : nsACString &aCharset,
1029 : bool *aHadCharset,
1030 : nsACString &aContentType)
1031 : {
1032 128 : net_ParseContentType(aTypeHeader, aContentType, aCharset, aHadCharset);
1033 128 : return NS_OK;
1034 : }
1035 :
1036 : NS_IMETHODIMP
1037 105049 : nsIOService::ProtocolHasFlags(nsIURI *uri,
1038 : PRUint32 flags,
1039 : bool *result)
1040 : {
1041 105049 : NS_ENSURE_ARG(uri);
1042 :
1043 105049 : *result = false;
1044 210098 : nsCAutoString scheme;
1045 105049 : nsresult rv = uri->GetScheme(scheme);
1046 105049 : NS_ENSURE_SUCCESS(rv, rv);
1047 :
1048 : PRUint32 protocolFlags;
1049 105049 : rv = GetProtocolFlags(scheme.get(), &protocolFlags);
1050 :
1051 105049 : if (NS_SUCCEEDED(rv)) {
1052 105049 : *result = (protocolFlags & flags) == flags;
1053 : }
1054 :
1055 105049 : return rv;
1056 : }
1057 :
1058 : NS_IMETHODIMP
1059 105022 : nsIOService::URIChainHasFlags(nsIURI *uri,
1060 : PRUint32 flags,
1061 : bool *result)
1062 : {
1063 105022 : nsresult rv = ProtocolHasFlags(uri, flags, result);
1064 105022 : NS_ENSURE_SUCCESS(rv, rv);
1065 :
1066 105022 : if (*result) {
1067 85531 : return rv;
1068 : }
1069 :
1070 : // Dig deeper into the chain. Note that this is not a do/while loop to
1071 : // avoid the extra addref/release on |uri| in the common (non-nested) case.
1072 38982 : nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(uri);
1073 38990 : while (nestedURI) {
1074 48 : nsCOMPtr<nsIURI> innerURI;
1075 24 : rv = nestedURI->GetInnerURI(getter_AddRefs(innerURI));
1076 24 : NS_ENSURE_SUCCESS(rv, rv);
1077 :
1078 24 : rv = ProtocolHasFlags(innerURI, flags, result);
1079 :
1080 24 : if (*result) {
1081 16 : return rv;
1082 : }
1083 :
1084 32 : nestedURI = do_QueryInterface(innerURI);
1085 : }
1086 :
1087 19475 : return rv;
1088 : }
1089 :
1090 : NS_IMETHODIMP
1091 2184 : nsIOService::ToImmutableURI(nsIURI* uri, nsIURI** result)
1092 : {
1093 2184 : if (!uri) {
1094 469 : *result = nsnull;
1095 469 : return NS_OK;
1096 : }
1097 :
1098 1715 : nsresult rv = NS_EnsureSafeToReturn(uri, result);
1099 1715 : NS_ENSURE_SUCCESS(rv, rv);
1100 :
1101 1715 : NS_TryToSetImmutable(*result);
1102 1715 : return NS_OK;
1103 : }
1104 :
1105 : NS_IMETHODIMP
1106 6 : nsIOService::NewSimpleNestedURI(nsIURI* aURI, nsIURI** aResult)
1107 : {
1108 6 : NS_ENSURE_ARG(aURI);
1109 :
1110 12 : nsCOMPtr<nsIURI> safeURI;
1111 6 : nsresult rv = NS_EnsureSafeToReturn(aURI, getter_AddRefs(safeURI));
1112 6 : NS_ENSURE_SUCCESS(rv, rv);
1113 :
1114 12 : NS_IF_ADDREF(*aResult = new nsSimpleNestedURI(safeURI));
1115 6 : return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
1116 : }
1117 :
1118 : NS_IMETHODIMP
1119 2806 : nsIOService::SetManageOfflineStatus(bool aManage) {
1120 2806 : nsresult rv = NS_OK;
1121 :
1122 : // SetManageOfflineStatus must throw when we fail to go from non-managed
1123 : // to managed. Usually because there is no link monitoring service
1124 : // available. Failure to do this switch is detected by a failure of
1125 : // TrackNetworkLinkStatusForOffline(). When there is no network link
1126 : // available during call to InitializeNetworkLinkService(), application is
1127 : // put to offline mode. And when we change mMangeOfflineStatus to false
1128 : // on the next line we get stuck on being offline even though the link
1129 : // becomes later available.
1130 2806 : bool wasManaged = mManageOfflineStatus;
1131 2806 : mManageOfflineStatus = aManage;
1132 :
1133 2806 : InitializeNetworkLinkService();
1134 :
1135 2806 : if (mManageOfflineStatus && !wasManaged) {
1136 0 : rv = TrackNetworkLinkStatusForOffline();
1137 0 : if (NS_FAILED(rv))
1138 0 : mManageOfflineStatus = false;
1139 : }
1140 2806 : return rv;
1141 : }
1142 :
1143 : NS_IMETHODIMP
1144 0 : nsIOService::GetManageOfflineStatus(bool* aManage) {
1145 0 : *aManage = mManageOfflineStatus;
1146 0 : return NS_OK;
1147 : }
1148 :
1149 : nsresult
1150 0 : nsIOService::TrackNetworkLinkStatusForOffline()
1151 : {
1152 0 : NS_ASSERTION(mManageOfflineStatus,
1153 : "Don't call this unless we're managing the offline status");
1154 0 : if (!mNetworkLinkService)
1155 0 : return NS_ERROR_FAILURE;
1156 :
1157 0 : if (mShutdown)
1158 0 : return NS_ERROR_NOT_AVAILABLE;
1159 :
1160 : // check to make sure this won't collide with Autodial
1161 0 : if (mSocketTransportService) {
1162 0 : bool autodialEnabled = false;
1163 0 : mSocketTransportService->GetAutodialEnabled(&autodialEnabled);
1164 : // If autodialing-on-link-down is enabled, check if the OS auto dial
1165 : // option is set to always autodial. If so, then we are
1166 : // always up for the purposes of offline management.
1167 0 : if (autodialEnabled) {
1168 : #if defined(XP_WIN) || defined(MOZ_PLATFORM_MAEMO)
1169 : // On Windows and Maemo (libconic) we should first check with the OS
1170 : // to see if autodial is enabled. If it is enabled then we are
1171 : // allowed to manage the offline state.
1172 : if(nsNativeConnectionHelper::IsAutodialEnabled())
1173 : return SetOffline(false);
1174 : #else
1175 0 : return SetOffline(false);
1176 : #endif
1177 : }
1178 : }
1179 :
1180 : bool isUp;
1181 0 : nsresult rv = mNetworkLinkService->GetIsLinkUp(&isUp);
1182 0 : NS_ENSURE_SUCCESS(rv, rv);
1183 0 : return SetOffline(!isUp);
1184 : }
1185 :
1186 : NS_IMETHODIMP
1187 0 : nsIOService::EscapeString(const nsACString& aString,
1188 : PRUint32 aEscapeType,
1189 : nsACString& aResult)
1190 : {
1191 0 : NS_ENSURE_ARG_RANGE(aEscapeType, 0, 4);
1192 :
1193 0 : nsCAutoString stringCopy(aString);
1194 0 : nsCString result;
1195 :
1196 0 : if (!NS_Escape(stringCopy, result, (nsEscapeMask) aEscapeType))
1197 0 : return NS_ERROR_OUT_OF_MEMORY;
1198 :
1199 0 : aResult.Assign(result);
1200 :
1201 0 : return NS_OK;
1202 : }
1203 :
1204 : NS_IMETHODIMP
1205 0 : nsIOService::EscapeURL(const nsACString &aStr,
1206 : PRUint32 aFlags, nsACString &aResult)
1207 : {
1208 0 : aResult.Truncate();
1209 0 : NS_EscapeURL(aStr.BeginReading(), aStr.Length(),
1210 0 : aFlags | esc_AlwaysCopy, aResult);
1211 0 : return NS_OK;
1212 : }
1213 :
1214 : NS_IMETHODIMP
1215 12 : nsIOService::UnescapeString(const nsACString &aStr,
1216 : PRUint32 aFlags, nsACString &aResult)
1217 : {
1218 12 : aResult.Truncate();
1219 12 : NS_UnescapeURL(aStr.BeginReading(), aStr.Length(),
1220 24 : aFlags | esc_AlwaysCopy, aResult);
1221 12 : return NS_OK;
1222 : }
1223 :
1224 : NS_IMETHODIMP
1225 27 : nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
1226 : nsACString &aCharset,
1227 : PRInt32 *aCharsetStart,
1228 : PRInt32 *aCharsetEnd,
1229 : bool *aHadCharset)
1230 : {
1231 54 : nsCAutoString ignored;
1232 : net_ParseContentType(aTypeHeader, ignored, aCharset, aHadCharset,
1233 27 : aCharsetStart, aCharsetEnd);
1234 27 : if (*aHadCharset && *aCharsetStart == *aCharsetEnd) {
1235 1 : *aHadCharset = false;
1236 : }
1237 27 : return NS_OK;
1238 : }
|