LCOV - app.info - extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp

LCOV - code coverage report
| Current view: | directory - extensions/gnomevfs - nsGnomeVFSProtocolHandler.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 337 | 33 | 9.8 %
| Date: | 2012-06-02 | Functions: | 42 | 10 | 23.8 %

           1                 : /* vim:set ts=2 sw=2 et cindent: */
           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 the Mozilla gnome-vfs extension.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is IBM Corporation.
          18                 :  * Portions created by IBM Corporation are Copyright (C) 2004
          19                 :  * IBM Corporation. All Rights Reserved.
          20                 :  *
          21                 :  * Contributor(s):
          22                 :  *   Darin Fisher <darin@meer.net>
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : // GnomeVFS v2.2.2 is missing G_BEGIN_DECLS in gnome-vfs-module-callback.h
          39                 : extern "C" {
          40                 : #include <libgnomevfs/gnome-vfs.h>
          41                 : #include <libgnomevfs/gnome-vfs-standard-callbacks.h>
          42                 : #include <libgnomevfs/gnome-vfs-mime-utils.h>
          43                 : }
          44                 :
          45                 : #include "nsServiceManagerUtils.h"
          46                 : #include "nsComponentManagerUtils.h"
          47                 : #include "mozilla/ModuleUtils.h"
          48                 : #include "nsIInterfaceRequestorUtils.h"
          49                 : #include "nsIPrefService.h"
          50                 : #include "nsIPrefBranch.h"
          51                 : #include "nsIObserver.h"
          52                 : #include "nsThreadUtils.h"
          53                 : #include "nsProxyRelease.h"
          54                 : #include "nsIAuthPrompt.h"
          55                 : #include "nsIStringBundle.h"
          56                 : #include "nsIStandardURL.h"
          57                 : #include "nsIURL.h"
          58                 : #include "nsMimeTypes.h"
          59                 : #include "nsNetUtil.h"
          60                 : #include "nsINetUtil.h"
          61                 : #include "nsAutoPtr.h"
          62                 : #include "nsError.h"
          63                 : #include "prlog.h"
          64                 : #include "prtime.h"
          65                 : #include "prprf.h"
          66                 : #include "plstr.h"
          67                 :
          68                 : #define MOZ_GNOMEVFS_SCHEME              "moz-gnomevfs"
          69                 : #define MOZ_GNOMEVFS_SUPPORTED_PROTOCOLS "network.gnomevfs.supported-protocols"
          70                 :
          71                 : //-----------------------------------------------------------------------------
          72                 :
          73                 : // NSPR_LOG_MODULES=gnomevfs:5
          74                 : #ifdef PR_LOGGING
          75                 : static PRLogModuleInfo *sGnomeVFSLog;
          76                 : #define LOG(args) PR_LOG(sGnomeVFSLog, PR_LOG_DEBUG, args)
          77                 : #else
          78                 : #define LOG(args)
          79                 : #endif
          80                 :
          81                 : //-----------------------------------------------------------------------------
          82                 :
          83                 : static nsresult
          84               0 : MapGnomeVFSResult(GnomeVFSResult result)
          85                 : {
          86               0 :   switch (result)
          87                 :   {
          88               0 :     case GNOME_VFS_OK:                           return NS_OK;
          89               0 :     case GNOME_VFS_ERROR_NOT_FOUND:              return NS_ERROR_FILE_NOT_FOUND;
          90               0 :     case GNOME_VFS_ERROR_INTERNAL:               return NS_ERROR_UNEXPECTED;
          91               0 :     case GNOME_VFS_ERROR_BAD_PARAMETERS:         return NS_ERROR_INVALID_ARG;
          92               0 :     case GNOME_VFS_ERROR_NOT_SUPPORTED:          return NS_ERROR_NOT_AVAILABLE;
          93               0 :     case GNOME_VFS_ERROR_CORRUPTED_DATA:         return NS_ERROR_FILE_CORRUPTED;
          94               0 :     case GNOME_VFS_ERROR_TOO_BIG:                return NS_ERROR_FILE_TOO_BIG;
          95               0 :     case GNOME_VFS_ERROR_NO_SPACE:               return NS_ERROR_FILE_NO_DEVICE_SPACE;
          96                 :     case GNOME_VFS_ERROR_READ_ONLY:
          97               0 :     case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM:  return NS_ERROR_FILE_READ_ONLY;
          98                 :     case GNOME_VFS_ERROR_INVALID_URI:
          99               0 :     case GNOME_VFS_ERROR_INVALID_HOST_NAME:      return NS_ERROR_MALFORMED_URI;
         100                 :     case GNOME_VFS_ERROR_ACCESS_DENIED:
         101                 :     case GNOME_VFS_ERROR_NOT_PERMITTED:
         102               0 :     case GNOME_VFS_ERROR_LOGIN_FAILED:           return NS_ERROR_FILE_ACCESS_DENIED;
         103               0 :     case GNOME_VFS_ERROR_EOF:                    return NS_BASE_STREAM_CLOSED;
         104               0 :     case GNOME_VFS_ERROR_NOT_A_DIRECTORY:        return NS_ERROR_FILE_NOT_DIRECTORY;
         105               0 :     case GNOME_VFS_ERROR_IN_PROGRESS:            return NS_ERROR_IN_PROGRESS;
         106               0 :     case GNOME_VFS_ERROR_FILE_EXISTS:            return NS_ERROR_FILE_ALREADY_EXISTS;
         107               0 :     case GNOME_VFS_ERROR_IS_DIRECTORY:           return NS_ERROR_FILE_IS_DIRECTORY;
         108               0 :     case GNOME_VFS_ERROR_NO_MEMORY:              return NS_ERROR_OUT_OF_MEMORY;
         109                 :     case GNOME_VFS_ERROR_HOST_NOT_FOUND:
         110               0 :     case GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS:    return NS_ERROR_UNKNOWN_HOST;
         111                 :     case GNOME_VFS_ERROR_CANCELLED:
         112               0 :     case GNOME_VFS_ERROR_INTERRUPTED:            return NS_ERROR_ABORT;
         113               0 :     case GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY:    return NS_ERROR_FILE_DIR_NOT_EMPTY;
         114               0 :     case GNOME_VFS_ERROR_NAME_TOO_LONG:          return NS_ERROR_FILE_NAME_TOO_LONG;
         115               0 :     case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE:  return NS_ERROR_UNKNOWN_PROTOCOL;
         116                 :
         117                 :     /* No special mapping for these error codes...
         118                 :
         119                 :     case GNOME_VFS_ERROR_GENERIC:
         120                 :     case GNOME_VFS_ERROR_IO:
         121                 :     case GNOME_VFS_ERROR_WRONG_FORMAT:
         122                 :     case GNOME_VFS_ERROR_BAD_FILE:
         123                 :     case GNOME_VFS_ERROR_NOT_OPEN:
         124                 :     case GNOME_VFS_ERROR_INVALID_OPEN_MODE:
         125                 :     case GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES:
         126                 :     case GNOME_VFS_ERROR_LOOP:
         127                 :     case GNOME_VFS_ERROR_DIRECTORY_BUSY:
         128                 :     case GNOME_VFS_ERROR_TOO_MANY_LINKS:
         129                 :     case GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM:
         130                 :     case GNOME_VFS_ERROR_SERVICE_OBSOLETE:
         131                 :     case GNOME_VFS_ERROR_PROTOCOL_ERROR:
         132                 :     case GNOME_VFS_ERROR_NO_MASTER_BROWSER:
         133                 :
         134                 :     */
         135                 :
         136                 :     // Make GCC happy
         137                 :     default:
         138               0 :       return NS_ERROR_FAILURE;
         139                 :   }
         140                 :
         141                 :   return NS_ERROR_FAILURE;
         142                 : }
         143                 :
         144                 : //-----------------------------------------------------------------------------
         145                 :
         146                 : static void
         147               0 : ProxiedAuthCallback(gconstpointer in,
         148                 :                     gsize         in_size,
         149                 :                     gpointer      out,
         150                 :                     gsize         out_size,
         151                 :                     gpointer      callback_data)
         152                 : {
         153                 :   GnomeVFSModuleCallbackAuthenticationIn *authIn =
         154               0 :       (GnomeVFSModuleCallbackAuthenticationIn *) in;
         155                 :   GnomeVFSModuleCallbackAuthenticationOut *authOut =
         156               0 :       (GnomeVFSModuleCallbackAuthenticationOut *) out;
         157                 :
         158               0 :   LOG(("gnomevfs: ProxiedAuthCallback [uri=%s]\n", authIn->uri));
         159                 :
         160                 :   // Without a channel, we have no way of getting a prompter.
         161               0 :   nsIChannel *channel = (nsIChannel *) callback_data;
         162               0 :   if (!channel)
         163               0 :     return;
         164                 :
         165               0 :   nsCOMPtr<nsIAuthPrompt> prompt;
         166               0 :   NS_QueryNotificationCallbacks(channel, prompt);
         167                 :
         168                 :   // If no auth prompt, then give up.  We could failover to using the
         169                 :   // WindowWatcher service, but that might defeat a consumer's purposeful
         170                 :   // attempt to disable authentication (for whatever reason).
         171               0 :   if (!prompt)
         172                 :     return;
         173                 :
         174                 :   // Parse out the host and port...
         175               0 :   nsCOMPtr<nsIURI> uri;
         176               0 :   channel->GetURI(getter_AddRefs(uri));
         177               0 :   if (!uri)
         178                 :     return;
         179                 :
         180                 : #ifdef DEBUG
         181                 :   {
         182                 :     //
         183                 :     // Make sure authIn->uri is consistent with the channel's URI.
         184                 :     //
         185                 :     // XXX This check is probably not IDN safe, and it might incorrectly
         186                 :     //     fire as a result of escaping differences.  It's unclear what
         187                 :     //     kind of transforms GnomeVFS might have applied to the URI spec
         188                 :     //     that we originally gave to it.  In spite of the likelihood of
         189                 :     //     false hits, this check is probably still valuable.
         190                 :     //
         191               0 :     nsCAutoString spec;
         192               0 :     uri->GetSpec(spec);
         193               0 :     int uriLen = strlen(authIn->uri);
         194               0 :     if (!StringHead(spec, uriLen).Equals(nsDependentCString(authIn->uri, uriLen)))
         195                 :     {
         196               0 :       LOG(("gnomevfs: [spec=%s authIn->uri=%s]\n", spec.get(), authIn->uri));
         197               0 :       NS_ERROR("URI mismatch");
         198                 :     }
         199                 :   }
         200                 : #endif
         201                 :
         202               0 :   nsCAutoString scheme, hostPort;
         203               0 :   uri->GetScheme(scheme);
         204               0 :   uri->GetHostPort(hostPort);
         205                 :
         206                 :   // It doesn't make sense for either of these strings to be empty.  What kind
         207                 :   // of funky URI is this?
         208               0 :   if (scheme.IsEmpty() || hostPort.IsEmpty())
         209                 :     return;
         210                 :
         211                 :   // Construct the single signon key.  Altering the value of this key will
         212                 :   // cause people's remembered passwords to be forgotten.  Think carefully
         213                 :   // before changing the way this key is constructed.
         214               0 :   nsAutoString key, realm;
         215                 :
         216               0 :   NS_ConvertUTF8toUTF16 dispHost(scheme);
         217               0 :   dispHost.Append(NS_LITERAL_STRING("://"));
         218               0 :   dispHost.Append(NS_ConvertUTF8toUTF16(hostPort));
         219                 :
         220               0 :   key = dispHost;
         221               0 :   if (authIn->realm)
         222                 :   {
         223                 :     // We assume the realm string is ASCII.  That might be a bogus assumption,
         224                 :     // but we have no idea what encoding GnomeVFS is using, so for now we'll
         225                 :     // limit ourselves to ISO-Latin-1.  XXX What is a better solution?
         226               0 :     realm.Append('"');
         227               0 :     realm.Append(NS_ConvertASCIItoUTF16(authIn->realm));
         228               0 :     realm.Append('"');
         229               0 :     key.Append(' ');
         230               0 :     key.Append(realm);
         231                 :   }
         232                 :
         233                 :   // Construct the message string...
         234                 :   //
         235                 :   // We use Necko's string bundle here.  This code really should be encapsulated
         236                 :   // behind some Necko API, after all this code is based closely on the code in
         237                 :   // nsHttpChannel.cpp.
         238                 :
         239                 :   nsCOMPtr<nsIStringBundleService> bundleSvc =
         240               0 :       do_GetService(NS_STRINGBUNDLE_CONTRACTID);
         241               0 :   if (!bundleSvc)
         242                 :     return;
         243                 :
         244               0 :   nsCOMPtr<nsIStringBundle> bundle;
         245               0 :   bundleSvc->CreateBundle("chrome://global/locale/commonDialogs.properties",
         246               0 :                           getter_AddRefs(bundle));
         247               0 :   if (!bundle)
         248                 :     return;
         249                 :
         250               0 :   nsString message;
         251               0 :   if (!realm.IsEmpty())
         252                 :   {
         253               0 :     const PRUnichar *strings[] = { realm.get(), dispHost.get() };
         254               0 :     bundle->FormatStringFromName(NS_LITERAL_STRING("EnterUserPasswordForRealm").get(),
         255               0 :                                  strings, 2, getter_Copies(message));
         256                 :   }
         257                 :   else
         258                 :   {
         259               0 :     const PRUnichar *strings[] = { dispHost.get() };
         260               0 :     bundle->FormatStringFromName(NS_LITERAL_STRING("EnterUserPasswordFor").get(),
         261               0 :                                  strings, 1, getter_Copies(message));
         262                 :   }
         263               0 :   if (message.IsEmpty())
         264                 :     return;
         265                 :
         266                 :   // Prompt the user...
         267                 :   nsresult rv;
         268               0 :   bool retval = false;
         269               0 :   PRUnichar *user = nsnull, *pass = nsnull;
         270                 :
         271               0 :   rv = prompt->PromptUsernameAndPassword(nsnull, message.get(),
         272                 :                                          key.get(),
         273                 :                                          nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
         274               0 :                                          &user, &pass, &retval);
         275               0 :   if (NS_FAILED(rv))
         276                 :     return;
         277               0 :   if (!retval || !user || !pass)
         278                 :     return;
         279                 :
         280                 :   // XXX We need to convert the UTF-16 username and password from our dialog to
         281                 :   // strings that GnomeVFS can understand.  It's unclear what encoding GnomeVFS
         282                 :   // expects, so for now we assume 7-bit ASCII.  Hopefully, we can get a better
         283                 :   // solution at some point.
         284                 :
         285                 :   // One copy is never enough...
         286               0 :   authOut->username = g_strdup(NS_LossyConvertUTF16toASCII(user).get());
         287               0 :   authOut->password = g_strdup(NS_LossyConvertUTF16toASCII(pass).get());
         288                 :
         289               0 :   nsMemory::Free(user);
         290               0 :   nsMemory::Free(pass);
         291                 : }
         292                 :
         293                 : struct nsGnomeVFSAuthCallbackEvent : public nsRunnable
         294               0 : {
         295                 :   gconstpointer in;
         296                 :   gsize         in_size;
         297                 :   gpointer      out;
         298                 :   gsize         out_size;
         299                 :   gpointer      callback_data;
         300                 :
         301               0 :   NS_IMETHOD Run() {
         302               0 :     ProxiedAuthCallback(in, in_size, out, out_size, callback_data);
         303               0 :     return NS_OK;
         304                 :   }
         305                 : };
         306                 :
         307                 : static void
         308               0 : AuthCallback(gconstpointer in,
         309                 :              gsize         in_size,
         310                 :              gpointer      out,
         311                 :              gsize         out_size,
         312                 :              gpointer      callback_data)
         313                 : {
         314                 :   // Need to proxy this callback over to the main thread.  Synchronous dispatch
         315                 :   // is required in order to provide data to the GnomeVFS callback.
         316                 :
         317               0 :   nsRefPtr<nsGnomeVFSAuthCallbackEvent> ev = new nsGnomeVFSAuthCallbackEvent();
         318               0 :   if (!ev)
         319                 :     return;  // OOM
         320                 :
         321               0 :   ev->in = in;
         322               0 :   ev->in_size = in_size;
         323               0 :   ev->out = out;
         324               0 :   ev->out_size = out_size;
         325               0 :   ev->callback_data = callback_data;
         326                 :
         327               0 :   NS_DispatchToMainThread(ev, NS_DISPATCH_SYNC);
         328                 : }
         329                 :
         330                 : //-----------------------------------------------------------------------------
         331                 :
         332                 : static gint
         333               0 : FileInfoComparator(gconstpointer a, gconstpointer b)
         334                 : {
         335               0 :   const GnomeVFSFileInfo *ia = (const GnomeVFSFileInfo *) a;
         336               0 :   const GnomeVFSFileInfo *ib = (const GnomeVFSFileInfo *) b;
         337                 :
         338               0 :   return strcasecmp(ia->name, ib->name);
         339                 : }
         340                 :
         341                 : //-----------------------------------------------------------------------------
         342                 :
         343                 : class nsGnomeVFSInputStream : public nsIInputStream
         344                 : {
         345                 :   public:
         346                 :     NS_DECL_ISUPPORTS
         347                 :     NS_DECL_NSIINPUTSTREAM
         348                 :
         349               0 :     nsGnomeVFSInputStream(const nsCString &uriSpec)
         350                 :       : mSpec(uriSpec)
         351                 :       , mChannel(nsnull)
         352                 :       , mHandle(nsnull)
         353                 :       , mBytesRemaining(PR_UINT32_MAX)
         354                 :       , mStatus(NS_OK)
         355                 :       , mDirList(nsnull)
         356                 :       , mDirListPtr(nsnull)
         357                 :       , mDirBufCursor(0)
         358               0 :       , mDirOpen(false) {}
         359                 :
         360               0 :    ~nsGnomeVFSInputStream() { Close(); }
         361                 :
         362               0 :     void SetChannel(nsIChannel *channel)
         363                 :     {
         364                 :       // We need to hold an owning reference to our channel.  This is done
         365                 :       // so we can access the channel's notification callbacks to acquire
         366                 :       // a reference to a nsIAuthPrompt if we need to handle a GnomeVFS
         367                 :       // authentication callback.
         368                 :       //
         369                 :       // However, the channel can only be accessed on the main thread, so
         370                 :       // we have to be very careful with ownership.  Moreover, it doesn't
         371                 :       // support threadsafe addref/release, so proxying is the answer.
         372                 :       //
         373                 :       // Also, it's important to note that this likely creates a reference
         374                 :       // cycle since the channel likely owns this stream.  This reference
         375                 :       // cycle is broken in our Close method.
         376                 :
         377               0 :       NS_ADDREF(mChannel = channel);
         378               0 :     }
         379                 :
         380                 :   private:
         381                 :     GnomeVFSResult DoOpen();
         382                 :     GnomeVFSResult DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead);
         383                 :     nsresult       SetContentTypeOfChannel(const char *contentType);
         384                 :
         385                 :   private:
         386                 :     nsCString                mSpec;
         387                 :     nsIChannel              *mChannel; // manually refcounted
         388                 :     GnomeVFSHandle          *mHandle;
         389                 :     PRUint32                 mBytesRemaining;
         390                 :     nsresult                 mStatus;
         391                 :     GList                   *mDirList;
         392                 :     GList                   *mDirListPtr;
         393                 :     nsCString                mDirBuf;
         394                 :     PRUint32                 mDirBufCursor;
         395                 :     bool                     mDirOpen;
         396                 : };
         397                 :
         398                 : GnomeVFSResult
         399               0 : nsGnomeVFSInputStream::DoOpen()
         400                 : {
         401                 :   GnomeVFSResult rv;
         402                 :
         403               0 :   NS_ASSERTION(mHandle == nsnull, "already open");
         404                 :
         405                 :   // Push a callback handler on the stack for this thread, so we can intercept
         406                 :   // authentication requests from GnomeVFS.  We'll use the channel to get a
         407                 :   // nsIAuthPrompt instance.
         408                 :
         409                 :   gnome_vfs_module_callback_push(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
         410               0 :                                  AuthCallback, mChannel, NULL);
         411                 :
         412                 :   // Query the mime type first (this could return NULL).
         413                 :   //
         414                 :   // XXX We need to do this up-front in order to determine how to open the URI.
         415                 :   //     Unfortunately, the error code GNOME_VFS_ERROR_IS_DIRECTORY is not
         416                 :   //     always returned by gnome_vfs_open when we pass it a URI to a directory!
         417                 :   //     Otherwise, we could have used that as a way to failover to opening the
         418                 :   //     URI as a directory.  Also, it would have been ideal if
         419                 :   //     gnome_vfs_get_file_info_from_handle were actually implemented by the
         420                 :   //     smb:// module, since that would have allowed us to potentially save a
         421                 :   //     round trip to the server to discover the mime type of the document in
         422                 :   //     the case where gnome_vfs_open would have been used.  (Oh well!  /me
         423                 :   //     throws hands up in the air and moves on...)
         424                 :
         425               0 :   GnomeVFSFileInfo info = {0};
         426                 :   rv = gnome_vfs_get_file_info(mSpec.get(), &info, GnomeVFSFileInfoOptions(
         427                 :                                GNOME_VFS_FILE_INFO_DEFAULT |
         428               0 :                                GNOME_VFS_FILE_INFO_FOLLOW_LINKS));
         429               0 :   if (rv == GNOME_VFS_OK)
         430                 :   {
         431               0 :     if (info.type == GNOME_VFS_FILE_TYPE_DIRECTORY)
         432                 :     {
         433                 :       rv = gnome_vfs_directory_list_load(&mDirList, mSpec.get(),
         434               0 :                                          GNOME_VFS_FILE_INFO_DEFAULT);
         435                 :
         436               0 :       LOG(("gnomevfs: gnome_vfs_directory_list_load returned %d (%s) [spec=\"%s\"]\n",
         437                 :           rv, gnome_vfs_result_to_string(rv), mSpec.get()));
         438                 :     }
         439                 :     else
         440                 :     {
         441               0 :       rv = gnome_vfs_open(&mHandle, mSpec.get(), GNOME_VFS_OPEN_READ);
         442                 :
         443               0 :       LOG(("gnomevfs: gnome_vfs_open returned %d (%s) [spec=\"%s\"]\n",
         444                 :           rv, gnome_vfs_result_to_string(rv), mSpec.get()));
         445                 :     }
         446                 :   }
         447                 :
         448               0 :   gnome_vfs_module_callback_pop(GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION);
         449                 :
         450               0 :   if (rv == GNOME_VFS_OK)
         451                 :   {
         452               0 :     if (mHandle)
         453                 :     {
         454                 :       // Here we set the content type of the channel to the value of the mime
         455                 :       // type determined by GnomeVFS.  However, if GnomeVFS is telling us that
         456                 :       // the document is binary, we'll ignore that and keep the channel's
         457                 :       // content type unspecified.  That will enable our content type sniffing
         458                 :       // algorithms.  This should provide more consistent mime type handling.
         459                 :
         460               0 :       if (info.mime_type && (strcmp(info.mime_type, APPLICATION_OCTET_STREAM) != 0))
         461               0 :         SetContentTypeOfChannel(info.mime_type);
         462                 :
         463                 :       // XXX truncates size from 64-bit to 32-bit
         464               0 :       mBytesRemaining = (PRUint32) info.size;
         465                 :
         466                 :       // Update the content length attribute on the channel.  We do this
         467                 :       // synchronously without proxying.  This hack is not as bad as it looks!
         468               0 :       if (mBytesRemaining != PR_UINT32_MAX)
         469               0 :         mChannel->SetContentLength(mBytesRemaining);
         470                 :     }
         471                 :     else
         472                 :     {
         473               0 :       mDirOpen = true;
         474                 :
         475                 :       // Sort mDirList
         476               0 :       mDirList = g_list_sort(mDirList, FileInfoComparator);
         477               0 :       mDirListPtr = mDirList;
         478                 :
         479                 :       // Write base URL (make sure it ends with a '/')
         480               0 :       mDirBuf.Append("300: ");
         481               0 :       mDirBuf.Append(mSpec);
         482               0 :       if (mSpec.get()[mSpec.Length() - 1] != '/')
         483               0 :         mDirBuf.Append('/');
         484               0 :       mDirBuf.Append('\n');
         485                 :
         486                 :       // Write column names
         487               0 :       mDirBuf.Append("200: filename content-length last-modified file-type\n");
         488                 :
         489                 :       // Write charset (assume UTF-8)
         490                 :       // XXX is this correct?
         491               0 :       mDirBuf.Append("301: UTF-8\n");
         492                 :
         493               0 :       SetContentTypeOfChannel(APPLICATION_HTTP_INDEX_FORMAT);
         494                 :     }
         495                 :   }
         496                 :
         497               0 :   gnome_vfs_file_info_clear(&info);
         498               0 :   return rv;
         499                 : }
         500                 :
         501                 : GnomeVFSResult
         502               0 : nsGnomeVFSInputStream::DoRead(char *aBuf, PRUint32 aCount, PRUint32 *aCountRead)
         503                 : {
         504                 :   GnomeVFSResult rv;
         505                 :
         506               0 :   if (mHandle)
         507                 :   {
         508                 :     GnomeVFSFileSize bytesRead;
         509               0 :     rv = gnome_vfs_read(mHandle, aBuf, aCount, &bytesRead);
         510               0 :     if (rv == GNOME_VFS_OK)
         511                 :     {
         512               0 :       *aCountRead = (PRUint32) bytesRead;
         513               0 :       mBytesRemaining -= *aCountRead;
         514                 :     }
         515                 :   }
         516               0 :   else if (mDirOpen)
         517                 :   {
         518               0 :     rv = GNOME_VFS_OK;
         519                 :
         520               0 :     while (aCount && rv != GNOME_VFS_ERROR_EOF)
         521                 :     {
         522                 :       // Copy data out of our buffer
         523               0 :       PRUint32 bufLen = mDirBuf.Length() - mDirBufCursor;
         524               0 :       if (bufLen)
         525                 :       {
         526               0 :         PRUint32 n = NS_MIN(bufLen, aCount);
         527               0 :         memcpy(aBuf, mDirBuf.get() + mDirBufCursor, n);
         528               0 :         *aCountRead += n;
         529               0 :         aBuf += n;
         530               0 :         aCount -= n;
         531               0 :         mDirBufCursor += n;
         532                 :       }
         533                 :
         534               0 :       if (!mDirListPtr)    // Are we at the end of the directory list?
         535                 :       {
         536               0 :         rv = GNOME_VFS_ERROR_EOF;
         537                 :       }
         538               0 :       else if (aCount)     // Do we need more data?
         539                 :       {
         540               0 :         GnomeVFSFileInfo *info = (GnomeVFSFileInfo *) mDirListPtr->data;
         541                 :
         542                 :         // Prune '.' and '..' from directory listing.
         543               0 :         if (info->name[0] == '.' &&
         544               0 :                (info->name[1] == '\0' ||
         545               0 :                    (info->name[1] == '.' && info->name[2] == '\0')))
         546                 :         {
         547               0 :           mDirListPtr = mDirListPtr->next;
         548               0 :           continue;
         549                 :         }
         550                 :
         551               0 :         mDirBuf.Assign("201: ");
         552                 :
         553                 :         // The "filename" field
         554               0 :         nsCString escName;
         555               0 :         nsCOMPtr<nsINetUtil> nu = do_GetService(NS_NETUTIL_CONTRACTID);
         556               0 :         if (nu) {
         557               0 :           nu->EscapeString(nsDependentCString(info->name),
         558               0 :                            nsINetUtil::ESCAPE_URL_PATH, escName);
         559                 :
         560               0 :           mDirBuf.Append(escName);
         561               0 :           mDirBuf.Append(' ');
         562                 :         }
         563                 :
         564                 :         // The "content-length" field
         565                 :         // XXX truncates size from 64-bit to 32-bit
         566               0 :         mDirBuf.AppendInt(PRInt32(info->size));
         567               0 :         mDirBuf.Append(' ');
         568                 :
         569                 :         // The "last-modified" field
         570                 :         //
         571                 :         // NSPR promises: PRTime is compatible with time_t
         572                 :         // we just need to convert from seconds to microseconds
         573                 :         PRExplodedTime tm;
         574               0 :         PRTime pt = ((PRTime) info->mtime) * 1000000;
         575               0 :         PR_ExplodeTime(pt, PR_GMTParameters, &tm);
         576                 :         {
         577                 :           char buf[64];
         578                 :           PR_FormatTimeUSEnglish(buf, sizeof(buf),
         579               0 :               "%a,%%20%d%%20%b%%20%Y%%20%H:%M:%S%%20GMT ", &tm);
         580               0 :           mDirBuf.Append(buf);
         581                 :         }
         582                 :
         583                 :         // The "file-type" field
         584               0 :         switch (info->type)
         585                 :         {
         586                 :           case GNOME_VFS_FILE_TYPE_REGULAR:
         587               0 :             mDirBuf.Append("FILE ");
         588               0 :             break;
         589                 :           case GNOME_VFS_FILE_TYPE_DIRECTORY:
         590               0 :             mDirBuf.Append("DIRECTORY ");
         591               0 :             break;
         592                 :           case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK:
         593               0 :             mDirBuf.Append("SYMBOLIC-LINK ");
         594               0 :             break;
         595                 :           default:
         596               0 :             break;
         597                 :         }
         598                 :
         599               0 :         mDirBuf.Append('\n');
         600                 :
         601               0 :         mDirBufCursor = 0;
         602               0 :         mDirListPtr = mDirListPtr->next;
         603                 :       }
         604                 :     }
         605                 :   }
         606                 :   else
         607                 :   {
         608               0 :     NS_NOTREACHED("reading from what?");
         609               0 :     rv = GNOME_VFS_ERROR_GENERIC;
         610                 :   }
         611                 :
         612               0 :   return rv;
         613                 : }
         614                 :
         615                 : // This class is used to implement SetContentTypeOfChannel.
         616                 : class nsGnomeVFSSetContentTypeEvent : public nsRunnable
         617               0 : {
         618                 :   public:
         619               0 :     nsGnomeVFSSetContentTypeEvent(nsIChannel *channel, const char *contentType)
         620               0 :       : mChannel(channel), mContentType(contentType)
         621                 :     {
         622                 :       // stash channel reference in mChannel.  no AddRef here!  see note
         623                 :       // in SetContentTypeOfchannel.
         624               0 :     }
         625                 :
         626               0 :     NS_IMETHOD Run()
         627                 :     {
         628               0 :       mChannel->SetContentType(mContentType);
         629               0 :       return NS_OK;
         630                 :     }
         631                 :
         632                 :   private:
         633                 :     nsIChannel *mChannel;
         634                 :     nsCString   mContentType;
         635                 : };
         636                 :
         637                 : nsresult
         638               0 : nsGnomeVFSInputStream::SetContentTypeOfChannel(const char *contentType)
         639                 : {
         640                 :   // We need to proxy this call over to the main thread.  We post an
         641                 :   // asynchronous event in this case so that we don't delay reading data, and
         642                 :   // we know that this is safe to do since the channel's reference will be
         643                 :   // released asynchronously as well.  We trust the ordering of the main
         644                 :   // thread's event queue to protect us against memory corruption.
         645                 :
         646                 :   nsresult rv;
         647                 :   nsCOMPtr<nsIRunnable> ev =
         648               0 :       new nsGnomeVFSSetContentTypeEvent(mChannel, contentType);
         649               0 :   if (!ev)
         650                 :   {
         651               0 :     rv = NS_ERROR_OUT_OF_MEMORY;
         652                 :   }
         653                 :   else
         654                 :   {
         655               0 :     rv = NS_DispatchToMainThread(ev);
         656                 :   }
         657               0 :   return rv;
         658                 : }
         659                 :
         660               0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsGnomeVFSInputStream, nsIInputStream)
         661                 :
         662                 : NS_IMETHODIMP
         663               0 : nsGnomeVFSInputStream::Close()
         664                 : {
         665               0 :   if (mHandle)
         666                 :   {
         667               0 :     gnome_vfs_close(mHandle);
         668               0 :     mHandle = nsnull;
         669                 :   }
         670                 :
         671               0 :   if (mDirList)
         672                 :   {
         673                 :     // Destroy the list of GnomeVFSFileInfo objects...
         674               0 :     g_list_foreach(mDirList, (GFunc) gnome_vfs_file_info_unref, nsnull);
         675               0 :     g_list_free(mDirList);
         676               0 :     mDirList = nsnull;
         677               0 :     mDirListPtr = nsnull;
         678                 :   }
         679                 :
         680               0 :   if (mChannel)
         681                 :   {
         682               0 :     nsresult rv = NS_OK;
         683                 :
         684               0 :     nsCOMPtr<nsIThread> thread = do_GetMainThread();
         685               0 :     if (thread)
         686               0 :       rv = NS_ProxyRelease(thread, mChannel);
         687                 :
         688               0 :     NS_ASSERTION(thread && NS_SUCCEEDED(rv), "leaking channel reference");
         689               0 :     mChannel = nsnull;
         690                 :   }
         691                 :
         692               0 :   mSpec.Truncate(); // free memory
         693                 :
         694                 :   // Prevent future reads from re-opening the handle.
         695               0 :   if (NS_SUCCEEDED(mStatus))
         696               0 :     mStatus = NS_BASE_STREAM_CLOSED;
         697                 :
         698               0 :   return NS_OK;
         699                 : }
         700                 :
         701                 : NS_IMETHODIMP
         702               0 : nsGnomeVFSInputStream::Available(PRUint32 *aResult)
         703                 : {
         704               0 :   if (NS_FAILED(mStatus))
         705               0 :     return mStatus;
         706                 :
         707               0 :   *aResult = mBytesRemaining;
         708               0 :   return NS_OK;
         709                 : }
         710                 :
         711                 : NS_IMETHODIMP
         712               0 : nsGnomeVFSInputStream::Read(char *aBuf,
         713                 :                             PRUint32 aCount,
         714                 :                             PRUint32 *aCountRead)
         715                 : {
         716               0 :   *aCountRead = 0;
         717                 :
         718               0 :   if (mStatus == NS_BASE_STREAM_CLOSED)
         719               0 :     return NS_OK;
         720               0 :   if (NS_FAILED(mStatus))
         721               0 :     return mStatus;
         722                 :
         723               0 :   GnomeVFSResult rv = GNOME_VFS_OK;
         724                 :
         725                 :   // If this is our first-time through here, then open the URI.
         726               0 :   if (!mHandle && !mDirOpen)
         727               0 :     rv = DoOpen();
         728                 :
         729               0 :   if (rv == GNOME_VFS_OK)
         730               0 :     rv = DoRead(aBuf, aCount, aCountRead);
         731                 :
         732               0 :   if (rv != GNOME_VFS_OK)
         733                 :   {
         734                 :     // If we reach here, we hit some kind of error.  EOF is not an error.
         735               0 :     mStatus = MapGnomeVFSResult(rv);
         736               0 :     if (mStatus == NS_BASE_STREAM_CLOSED)
         737               0 :       return NS_OK;
         738                 :
         739               0 :     LOG(("gnomevfs: result %d [%s] mapped to 0x%x\n",
         740                 :         rv, gnome_vfs_result_to_string(rv), mStatus));
         741                 :   }
         742               0 :   return mStatus;
         743                 : }
         744                 :
         745                 : NS_IMETHODIMP
         746               0 : nsGnomeVFSInputStream::ReadSegments(nsWriteSegmentFun aWriter,
         747                 :                                     void *aClosure,
         748                 :                                     PRUint32 aCount,
         749                 :                                     PRUint32 *aResult)
         750                 : {
         751                 :   // There is no way to implement this using GnomeVFS, but fortunately
         752                 :   // that doesn't matter.  Because we are a blocking input stream, Necko
         753                 :   // isn't going to call our ReadSegments method.
         754               0 :   NS_NOTREACHED("nsGnomeVFSInputStream::ReadSegments");
         755               0 :   return NS_ERROR_NOT_IMPLEMENTED;
         756                 : }
         757                 :
         758                 : NS_IMETHODIMP
         759               0 : nsGnomeVFSInputStream::IsNonBlocking(bool *aResult)
         760                 : {
         761               0 :   *aResult = false;
         762               0 :   return NS_OK;
         763                 : }
         764                 :
         765                 : //-----------------------------------------------------------------------------
         766                 :
         767                 : class nsGnomeVFSProtocolHandler : public nsIProtocolHandler
         768                 :                                 , public nsIObserver
         769              26 : {
         770                 :   public:
         771                 :     NS_DECL_ISUPPORTS
         772                 :     NS_DECL_NSIPROTOCOLHANDLER
         773                 :     NS_DECL_NSIOBSERVER
         774                 :
         775                 :     nsresult Init();
         776                 :
         777                 :   private:
         778                 :     void   InitSupportedProtocolsPref(nsIPrefBranch *prefs);
         779                 :     bool IsSupportedProtocol(const nsCString &spec);
         780                 :
         781                 :     nsCString mSupportedProtocols;
         782                 : };
         783                 :
         784            1240 : NS_IMPL_ISUPPORTS2(nsGnomeVFSProtocolHandler, nsIProtocolHandler, nsIObserver)
         785                 :
         786                 : nsresult
         787              13 : nsGnomeVFSProtocolHandler::Init()
         788                 : {
         789                 : #ifdef PR_LOGGING
         790              13 :   sGnomeVFSLog = PR_NewLogModule("gnomevfs");
         791                 : #endif
         792                 :
         793              13 :   if (!gnome_vfs_initialized())
         794                 :   {
         795              12 :     if (!gnome_vfs_init())
         796                 :     {
         797               0 :       NS_WARNING("gnome_vfs_init failed");
         798               0 :       return NS_ERROR_UNEXPECTED;
         799                 :     }
         800                 :   }
         801                 :
         802              26 :   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
         803              13 :   if (prefs)
         804                 :   {
         805              13 :     InitSupportedProtocolsPref(prefs);
         806              13 :     prefs->AddObserver(MOZ_GNOMEVFS_SUPPORTED_PROTOCOLS, this, false);
         807                 :   }
         808                 :
         809              13 :   return NS_OK;
         810                 : }
         811                 :
         812                 : void
         813              13 : nsGnomeVFSProtocolHandler::InitSupportedProtocolsPref(nsIPrefBranch *prefs)
         814                 : {
         815                 :   // read preferences
         816                 :   nsresult rv = prefs->GetCharPref(MOZ_GNOMEVFS_SUPPORTED_PROTOCOLS,
         817              13 :                                    getter_Copies(mSupportedProtocols));
         818              13 :   if (NS_SUCCEEDED(rv)) {
         819               0 :     mSupportedProtocols.StripWhitespace();
         820               0 :     ToLowerCase(mSupportedProtocols);
         821                 :   }
         822                 :   else
         823              13 :     mSupportedProtocols.Assign("smb:,sftp:"); // use defaults
         824                 :
         825              13 :   LOG(("gnomevfs: supported protocols \"%s\"\n", mSupportedProtocols.get()));
         826              13 : }
         827                 :
         828                 : bool
         829             209 : nsGnomeVFSProtocolHandler::IsSupportedProtocol(const nsCString &aSpec)
         830                 : {
         831             209 :   const char *specString = aSpec.get();
         832             209 :   const char *colon = strchr(specString, ':');
         833             209 :   if (!colon)
         834               0 :     return false;
         835                 :
         836             209 :   PRUint32 length = colon - specString + 1;
         837                 :
         838                 :   // <scheme> + ':'
         839             418 :   nsCString scheme(specString, length);
         840                 :
         841             209 :   char *found = PL_strcasestr(mSupportedProtocols.get(), scheme.get());
         842             209 :   if (!found)
         843             209 :     return false;
         844                 :
         845               0 :   if (found[length] != ',' && found[length] != '\0')
         846               0 :     return false;
         847                 :
         848               0 :   return true;
         849                 : }
         850                 :
         851                 : NS_IMETHODIMP
         852               0 : nsGnomeVFSProtocolHandler::GetScheme(nsACString &aScheme)
         853                 : {
         854               0 :   aScheme.Assign(MOZ_GNOMEVFS_SCHEME);
         855               0 :   return NS_OK;
         856                 : }
         857                 :
         858                 : NS_IMETHODIMP
         859               0 : nsGnomeVFSProtocolHandler::GetDefaultPort(PRInt32 *aDefaultPort)
         860                 : {
         861               0 :   *aDefaultPort = -1;
         862               0 :   return NS_OK;
         863                 : }
         864                 :
         865                 : NS_IMETHODIMP
         866               0 : nsGnomeVFSProtocolHandler::GetProtocolFlags(PRUint32 *aProtocolFlags)
         867                 : {
         868                 :   // Is URI_STD true of all GnomeVFS URI types?
         869               0 :   *aProtocolFlags = URI_STD | URI_DANGEROUS_TO_LOAD;
         870               0 :   return NS_OK;
         871                 : }
         872                 :
         873                 : NS_IMETHODIMP
         874             209 : nsGnomeVFSProtocolHandler::NewURI(const nsACString &aSpec,
         875                 :                                   const char *aOriginCharset,
         876                 :                                   nsIURI *aBaseURI,
         877                 :                                   nsIURI **aResult)
         878                 : {
         879             418 :   const nsCString flatSpec(aSpec);
         880             209 :   LOG(("gnomevfs: NewURI [spec=%s]\n", flatSpec.get()));
         881                 :
         882             209 :   if (!aBaseURI)
         883                 :   {
         884                 :     //
         885                 :     // XXX This check is used to limit the gnome-vfs protocols we support.  For
         886                 :     //     security reasons, it is best that we limit the protocols we support to
         887                 :     //     those with known characteristics.  We might want to lessen this
         888                 :     //     restriction if it proves to be too heavy handed.  A black list of
         889                 :     //     protocols we don't want to support might be better.  For example, we
         890                 :     //     probably don't want to try to load "start-here:" inside the browser.
         891                 :     //     There are others that fall into this category, which are best handled
         892                 :     //     externally by Nautilus (or another app like it).
         893                 :     //
         894             209 :     if (!IsSupportedProtocol(flatSpec))
         895             209 :       return NS_ERROR_UNKNOWN_PROTOCOL;
         896                 :
         897                 :     // Verify that GnomeVFS supports this URI scheme.
         898               0 :     GnomeVFSURI *uri = gnome_vfs_uri_new(flatSpec.get());
         899               0 :     if (!uri)
         900               0 :       return NS_ERROR_UNKNOWN_PROTOCOL;
         901                 :   }
         902                 :
         903                 :   //
         904                 :   // XXX Can we really assume that all gnome-vfs URIs can be parsed using
         905                 :   //     nsStandardURL?  We probably really need to implement nsIURI/nsIURL
         906                 :   //     in terms of the gnome_vfs_uri_XXX methods, but at least this works
         907                 :   //     correctly for smb:// URLs ;-)
         908                 :   //
         909                 :   //     Also, it might not be possible to fully implement nsIURI/nsIURL in
         910                 :   //     terms of GnomeVFSURI since some Necko methods have no GnomeVFS
         911                 :   //     equivalent.
         912                 :   //
         913                 :   nsresult rv;
         914                 :   nsCOMPtr<nsIStandardURL> url =
         915               0 :       do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
         916               0 :   if (NS_FAILED(rv))
         917               0 :     return rv;
         918                 :
         919               0 :   rv = url->Init(nsIStandardURL::URLTYPE_STANDARD, -1, flatSpec,
         920               0 :                  aOriginCharset, aBaseURI);
         921               0 :   if (NS_SUCCEEDED(rv))
         922               0 :     rv = CallQueryInterface(url, aResult);
         923                 :
         924               0 :   return rv;
         925                 : }
         926                 :
         927                 : NS_IMETHODIMP
         928               0 : nsGnomeVFSProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **aResult)
         929                 : {
         930               0 :   NS_ENSURE_ARG_POINTER(aURI);
         931                 :   nsresult rv;
         932                 :
         933               0 :   nsCAutoString spec;
         934               0 :   rv = aURI->GetSpec(spec);
         935               0 :   if (NS_FAILED(rv))
         936               0 :     return rv;
         937                 :
         938               0 :   nsRefPtr<nsGnomeVFSInputStream> stream = new nsGnomeVFSInputStream(spec);
         939               0 :   if (!stream)
         940                 :   {
         941               0 :     rv = NS_ERROR_OUT_OF_MEMORY;
         942                 :   }
         943                 :   else
         944                 :   {
         945                 :     // start out assuming an unknown content-type.  we'll set the content-type
         946                 :     // to something better once we open the URI.
         947                 :     rv = NS_NewInputStreamChannel(aResult, aURI, stream,
         948               0 :                                   NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE));
         949               0 :     if (NS_SUCCEEDED(rv))
         950               0 :       stream->SetChannel(*aResult);
         951                 :   }
         952               0 :   return rv;
         953                 : }
         954                 :
         955                 : NS_IMETHODIMP
         956               0 : nsGnomeVFSProtocolHandler::AllowPort(PRInt32 aPort,
         957                 :                                      const char *aScheme,
         958                 :                                      bool *aResult)
         959                 : {
         960                 :   // Don't override anything.
         961               0 :   *aResult = false;
         962               0 :   return NS_OK;
         963                 : }
         964                 :
         965                 : NS_IMETHODIMP
         966               0 : nsGnomeVFSProtocolHandler::Observe(nsISupports *aSubject,
         967                 :                                    const char *aTopic,
         968                 :                                    const PRUnichar *aData)
         969                 : {
         970               0 :   if (strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
         971               0 :     nsCOMPtr<nsIPrefBranch> prefs = do_QueryInterface(aSubject);
         972               0 :     InitSupportedProtocolsPref(prefs);
         973                 :   }
         974               0 :   return NS_OK;
         975                 : }
         976                 :
         977                 : //-----------------------------------------------------------------------------
         978                 :
         979                 : #define NS_GNOMEVFSPROTOCOLHANDLER_CID               \
         980                 : { /* 9b6dc177-a2e4-49e1-9c98-0a8384de7f6c */         \
         981                 :     0x9b6dc177,                                      \
         982                 :     0xa2e4,                                          \
         983                 :     0x49e1,                                          \
         984                 :     {0x9c, 0x98, 0x0a, 0x83, 0x84, 0xde, 0x7f, 0x6c} \
         985                 : }
         986                 :
         987              26 : NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGnomeVFSProtocolHandler, Init)
         988                 : NS_DEFINE_NAMED_CID(NS_GNOMEVFSPROTOCOLHANDLER_CID);
         989                 :
         990                 : static const mozilla::Module::CIDEntry kVFSCIDs[] = {
         991                 :   { &kNS_GNOMEVFSPROTOCOLHANDLER_CID, false, NULL, nsGnomeVFSProtocolHandlerConstructor },
         992                 :   { NULL }
         993                 : };
         994                 :
         995                 : static const mozilla::Module::ContractIDEntry kVFSContracts[] = {
         996                 :   { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX MOZ_GNOMEVFS_SCHEME, &kNS_GNOMEVFSPROTOCOLHANDLER_CID },
         997                 :   { NULL }
         998                 : };
         999                 :
        1000                 : static const mozilla::Module kVFSModule = {
        1001                 :   mozilla::Module::kVersion,
        1002                 :   kVFSCIDs,
        1003                 :   kVFSContracts
        1004                 : };
        1005                 :
        1006                 : NSMODULE_DEFN(nsGnomeVFSModule) = &kVFSModule;

Generated by: LCOV version 1.7