LCOV - code coverage report
Current view: directory - extensions/cookie - nsPermissionManager.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 444 325 73.2 %
Date: 2012-06-02 Functions: 38 34 89.5 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Michiel van Leeuwen (mvl@exedo.nl)
      24                 :  *   Daniel Witte (dwitte@stanford.edu)
      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 "mozilla/dom/ContentParent.h"
      41                 : #include "mozilla/dom/ContentChild.h"
      42                 : #include "mozilla/unused.h"
      43                 : #include "nsPermissionManager.h"
      44                 : #include "nsPermission.h"
      45                 : #include "nsCRT.h"
      46                 : #include "nsNetUtil.h"
      47                 : #include "nsCOMArray.h"
      48                 : #include "nsArrayEnumerator.h"
      49                 : #include "nsTArray.h"
      50                 : #include "nsReadableUtils.h"
      51                 : #include "nsILineInputStream.h"
      52                 : #include "nsIIDNService.h"
      53                 : #include "nsAppDirectoryServiceDefs.h"
      54                 : #include "prprf.h"
      55                 : #include "mozIStorageService.h"
      56                 : #include "mozIStorageStatement.h"
      57                 : #include "mozIStorageConnection.h"
      58                 : #include "mozStorageHelper.h"
      59                 : #include "mozStorageCID.h"
      60                 : #include "nsXULAppAPI.h"
      61                 : 
      62                 : static nsPermissionManager *gPermissionManager = nsnull;
      63                 : 
      64                 : using mozilla::dom::ContentParent;
      65                 : using mozilla::dom::ContentChild;
      66                 : using mozilla::unused; // ha!
      67                 : 
      68                 : static bool
      69            2518 : IsChildProcess()
      70                 : {
      71            2518 :   return XRE_GetProcessType() == GeckoProcessType_Content;
      72                 : }
      73                 : 
      74                 : /**
      75                 :  * @returns The child process object, or if we are not in the child
      76                 :  *          process, nsnull.
      77                 :  */
      78                 : static ContentChild*
      79               0 : ChildProcess()
      80                 : {
      81               0 :   if (IsChildProcess()) {
      82               0 :     ContentChild* cpc = ContentChild::GetSingleton();
      83               0 :     if (!cpc)
      84               0 :       NS_RUNTIMEABORT("Content Process is NULL!");
      85               0 :     return cpc;
      86                 :   }
      87                 : 
      88               0 :   return nsnull;
      89                 : }
      90                 : 
      91                 : 
      92                 : #define ENSURE_NOT_CHILD_PROCESS_(onError) \
      93                 :   PR_BEGIN_MACRO \
      94                 :   if (IsChildProcess()) { \
      95                 :     NS_ERROR("Cannot perform action in content process!"); \
      96                 :     onError \
      97                 :   } \
      98                 :   PR_END_MACRO
      99                 : 
     100                 : #define ENSURE_NOT_CHILD_PROCESS \
     101                 :   ENSURE_NOT_CHILD_PROCESS_({ return NS_ERROR_NOT_AVAILABLE; })
     102                 : 
     103                 : #define ENSURE_NOT_CHILD_PROCESS_NORET \
     104                 :   ENSURE_NOT_CHILD_PROCESS_()
     105                 : 
     106                 : ////////////////////////////////////////////////////////////////////////////////
     107                 : 
     108                 : #define PL_ARENA_CONST_ALIGN_MASK 3
     109                 : #include "plarena.h"
     110                 : 
     111                 : static PLArenaPool *gHostArena = nsnull;
     112                 : 
     113                 : // making sHostArena 512b for nice allocation
     114                 : // growing is quite cheap
     115                 : #define HOST_ARENA_SIZE 512
     116                 : 
     117                 : // equivalent to strdup() - does no error checking,
     118                 : // we're assuming we're only called with a valid pointer
     119                 : static char *
     120             445 : ArenaStrDup(const char* str, PLArenaPool* aArena)
     121                 : {
     122                 :   void* mem;
     123             445 :   const PRUint32 size = strlen(str) + 1;
     124             445 :   PL_ARENA_ALLOCATE(mem, aArena, size);
     125             445 :   if (mem)
     126             445 :     memcpy(mem, str, size);
     127             445 :   return static_cast<char*>(mem);
     128                 : }
     129                 : 
     130             445 : nsHostEntry::nsHostEntry(const char* aHost)
     131                 : {
     132             445 :   mHost = ArenaStrDup(aHost, gHostArena);
     133             445 : }
     134                 : 
     135                 : // XXX this can fail on OOM
     136               0 : nsHostEntry::nsHostEntry(const nsHostEntry& toCopy)
     137                 :  : mHost(toCopy.mHost)
     138               0 :  , mPermissions(toCopy.mPermissions)
     139                 : {
     140               0 : }
     141                 : 
     142                 : ////////////////////////////////////////////////////////////////////////////////
     143                 : // nsPermissionManager Implementation
     144                 : 
     145                 : static const char kPermissionsFileName[] = "permissions.sqlite";
     146                 : #define HOSTS_SCHEMA_VERSION 2
     147                 : 
     148                 : static const char kHostpermFileName[] = "hostperm.1";
     149                 : 
     150                 : static const char kPermissionChangeNotification[] = PERM_CHANGE_NOTIFICATION;
     151                 : 
     152           13777 : NS_IMPL_ISUPPORTS3(nsPermissionManager, nsIPermissionManager, nsIObserver, nsISupportsWeakReference)
     153                 : 
     154             400 : nsPermissionManager::nsPermissionManager()
     155             400 :  : mLargestID(0)
     156                 : {
     157             400 : }
     158                 : 
     159            1194 : nsPermissionManager::~nsPermissionManager()
     160                 : {
     161             398 :   RemoveAllFromMemory();
     162             398 :   gPermissionManager = nsnull;
     163            1592 : }
     164                 : 
     165                 : // static
     166                 : nsIPermissionManager*
     167             400 : nsPermissionManager::GetXPCOMSingleton()
     168                 : {
     169             400 :   if (gPermissionManager) {
     170               0 :     NS_ADDREF(gPermissionManager);
     171               0 :     return gPermissionManager;
     172                 :   }
     173                 : 
     174                 :   // Create a new singleton nsPermissionManager.
     175                 :   // We AddRef only once since XPCOM has rules about the ordering of module
     176                 :   // teardowns - by the time our module destructor is called, it's too late to
     177                 :   // Release our members, since GC cycles have already been completed and
     178                 :   // would result in serious leaks.
     179                 :   // See bug 209571.
     180             400 :   gPermissionManager = new nsPermissionManager();
     181             400 :   if (gPermissionManager) {
     182             400 :     NS_ADDREF(gPermissionManager);
     183             400 :     if (NS_FAILED(gPermissionManager->Init())) {
     184               0 :       NS_RELEASE(gPermissionManager);
     185                 :     }
     186                 :   }
     187                 : 
     188             400 :   return gPermissionManager;
     189                 : }
     190                 : 
     191                 : nsresult
     192             400 : nsPermissionManager::Init()
     193                 : {
     194                 :   nsresult rv;
     195                 : 
     196             400 :   if (!mHostTable.Init()) {
     197               0 :     return NS_ERROR_OUT_OF_MEMORY;
     198                 :   }
     199                 : 
     200             400 :   mObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
     201             400 :   if (NS_SUCCEEDED(rv)) {
     202             400 :     mObserverService->AddObserver(this, "profile-before-change", true);
     203             400 :     mObserverService->AddObserver(this, "profile-do-change", true);
     204                 :   }
     205                 : 
     206             400 :   if (IsChildProcess()) {
     207                 :     // Get the permissions from the parent process
     208               0 :     InfallibleTArray<IPC::Permission> perms;
     209               0 :     ChildProcess()->SendReadPermissions(&perms);
     210                 : 
     211               0 :     for (PRUint32 i = 0; i < perms.Length(); i++) {
     212               0 :       const IPC::Permission &perm = perms[i];
     213                 :       AddInternal(perm.host, perm.type, perm.capability, 0, perm.expireType,
     214               0 :                   perm.expireTime, eNotify, eNoDBOperation);
     215                 :     }
     216                 : 
     217                 :     // Stop here; we don't need the DB in the child process
     218               0 :     return NS_OK;
     219                 :   }
     220                 : 
     221                 :   // ignore failure here, since it's non-fatal (we can run fine without
     222                 :   // persistent storage - e.g. if there's no profile).
     223                 :   // XXX should we tell the user about this?
     224             400 :   InitDB(false);
     225                 : 
     226             400 :   return NS_OK;
     227                 : }
     228                 : 
     229                 : nsresult
     230             401 : nsPermissionManager::InitDB(bool aRemoveFile)
     231                 : {
     232             802 :   nsCOMPtr<nsIFile> permissionsFile;
     233             401 :   NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
     234             401 :   if (!permissionsFile)
     235             113 :     return NS_ERROR_UNEXPECTED;
     236                 : 
     237             288 :   nsresult rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kPermissionsFileName));
     238             288 :   NS_ENSURE_SUCCESS(rv, rv);
     239                 : 
     240             288 :   if (aRemoveFile) {
     241               1 :     bool exists = false;
     242               1 :     rv = permissionsFile->Exists(&exists);
     243               1 :     NS_ENSURE_SUCCESS(rv, rv);
     244               1 :     if (exists) {
     245               1 :       rv = permissionsFile->Remove(false);
     246               1 :       NS_ENSURE_SUCCESS(rv, rv);
     247                 :     }
     248                 :   }
     249                 : 
     250             576 :   nsCOMPtr<mozIStorageService> storage = do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
     251             288 :   if (!storage)
     252               0 :     return NS_ERROR_UNEXPECTED;
     253                 : 
     254                 :   // cache a connection to the hosts database
     255             288 :   rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
     256             288 :   NS_ENSURE_SUCCESS(rv, rv);
     257                 : 
     258                 :   bool ready;
     259             288 :   mDBConn->GetConnectionReady(&ready);
     260             288 :   if (!ready) {
     261                 :     // delete and try again
     262               0 :     rv = permissionsFile->Remove(false);
     263               0 :     NS_ENSURE_SUCCESS(rv, rv);
     264                 : 
     265               0 :     rv = storage->OpenDatabase(permissionsFile, getter_AddRefs(mDBConn));
     266               0 :     NS_ENSURE_SUCCESS(rv, rv);
     267                 : 
     268               0 :     mDBConn->GetConnectionReady(&ready);
     269               0 :     if (!ready)
     270               0 :       return NS_ERROR_UNEXPECTED;
     271                 :   }
     272                 : 
     273             288 :   bool tableExists = false;
     274             288 :   mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts"), &tableExists);
     275             288 :   if (!tableExists) {
     276             288 :     rv = CreateTable();
     277             288 :     NS_ENSURE_SUCCESS(rv, rv);
     278                 : 
     279                 :   } else {
     280                 :     // table already exists; check the schema version before reading
     281                 :     PRInt32 dbSchemaVersion;
     282               0 :     rv = mDBConn->GetSchemaVersion(&dbSchemaVersion);
     283               0 :     NS_ENSURE_SUCCESS(rv, rv);
     284                 : 
     285               0 :     switch (dbSchemaVersion) {
     286                 :     // upgrading.
     287                 :     // every time you increment the database schema, you need to implement
     288                 :     // the upgrading code from the previous version to the new one.
     289                 :     // fall through to current version
     290                 : 
     291                 :     case 1:
     292                 :       {
     293                 :         // previous non-expiry version of database.  Upgrade it by adding the
     294                 :         // expiration columns
     295               0 :         rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     296               0 :               "ALTER TABLE moz_hosts ADD expireType INTEGER"));
     297               0 :         NS_ENSURE_SUCCESS(rv, rv);
     298                 : 
     299               0 :         rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     300               0 :               "ALTER TABLE moz_hosts ADD expireTime INTEGER"));
     301               0 :         NS_ENSURE_SUCCESS(rv, rv);
     302                 : 
     303               0 :         rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
     304               0 :         NS_ENSURE_SUCCESS(rv, rv);
     305                 :       }
     306                 : 
     307                 :       // fall through to the next upgrade
     308                 :       
     309                 :     // current version.
     310                 :     case HOSTS_SCHEMA_VERSION:
     311               0 :       break;
     312                 : 
     313                 :     case 0:
     314                 :       {
     315               0 :         NS_WARNING("couldn't get schema version!");
     316                 :           
     317                 :         // the table may be usable; someone might've just clobbered the schema
     318                 :         // version. we can treat this case like a downgrade using the codepath
     319                 :         // below, by verifying the columns we care about are all there. for now,
     320                 :         // re-set the schema version in the db, in case the checks succeed (if
     321                 :         // they don't, we're dropping the table anyway).
     322               0 :         rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
     323               0 :         NS_ENSURE_SUCCESS(rv, rv);
     324                 :       }
     325                 :       // fall through to downgrade check
     326                 : 
     327                 :     // downgrading.
     328                 :     // if columns have been added to the table, we can still use the ones we
     329                 :     // understand safely. if columns have been deleted or altered, just
     330                 :     // blow away the table and start from scratch! if you change the way
     331                 :     // a column is interpreted, make sure you also change its name so this
     332                 :     // check will catch it.
     333                 :     default:
     334                 :       {
     335                 :         // check if all the expected columns exist
     336               0 :         nsCOMPtr<mozIStorageStatement> stmt;
     337               0 :         rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
     338                 :           "SELECT host, type, permission, expireType, expireTime FROM moz_hosts"),
     339               0 :           getter_AddRefs(stmt));
     340               0 :         if (NS_SUCCEEDED(rv))
     341                 :           break;
     342                 : 
     343                 :         // our columns aren't there - drop the table!
     344               0 :         rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_hosts"));
     345               0 :         NS_ENSURE_SUCCESS(rv, rv);
     346                 : 
     347               0 :         rv = CreateTable();
     348               0 :         NS_ENSURE_SUCCESS(rv, rv);
     349                 :       }
     350               0 :       break;
     351                 :     }
     352                 :   }
     353                 : 
     354                 :   // make operations on the table asynchronous, for performance
     355             288 :   mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA synchronous = OFF"));
     356                 : 
     357                 :   // cache frequently used statements (for insertion, deletion, and updating)
     358             576 :   rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
     359                 :     "INSERT INTO moz_hosts "
     360                 :     "(id, host, type, permission, expireType, expireTime) "
     361             576 :     "VALUES (?1, ?2, ?3, ?4, ?5, ?6)"), getter_AddRefs(mStmtInsert));
     362             288 :   NS_ENSURE_SUCCESS(rv, rv);
     363                 : 
     364             576 :   rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
     365                 :     "DELETE FROM moz_hosts "
     366             576 :     "WHERE id = ?1"), getter_AddRefs(mStmtDelete));
     367             288 :   NS_ENSURE_SUCCESS(rv, rv);
     368                 : 
     369             576 :   rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
     370                 :     "UPDATE moz_hosts "
     371                 :     "SET permission = ?2, expireType= ?3, expireTime = ?4 WHERE id = ?1"),
     372             576 :     getter_AddRefs(mStmtUpdate));
     373             288 :   NS_ENSURE_SUCCESS(rv, rv);
     374                 : 
     375                 :   // check whether to import or just read in the db
     376             288 :   if (tableExists)
     377               0 :     return Read();
     378                 : 
     379             288 :   return Import();
     380                 : }
     381                 : 
     382                 : // sets the schema version and creates the moz_hosts table.
     383                 : nsresult
     384             288 : nsPermissionManager::CreateTable()
     385                 : {
     386                 :   // set the schema version, before creating the table
     387             288 :   nsresult rv = mDBConn->SetSchemaVersion(HOSTS_SCHEMA_VERSION);
     388             288 :   if (NS_FAILED(rv)) return rv;
     389                 : 
     390                 :   // create the table
     391                 :   // SQL also lives in automation.py.in. If you change this SQL change that
     392                 :   // one too.
     393             576 :   return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
     394                 :     "CREATE TABLE moz_hosts ("
     395                 :       " id INTEGER PRIMARY KEY"
     396                 :       ",host TEXT"
     397                 :       ",type TEXT"
     398                 :       ",permission INTEGER"
     399                 :       ",expireType INTEGER"
     400                 :       ",expireTime INTEGER"
     401             288 :     ")"));
     402                 : }
     403                 : 
     404                 : NS_IMETHODIMP
     405             484 : nsPermissionManager::Add(nsIURI     *aURI,
     406                 :                          const char *aType,
     407                 :                          PRUint32    aPermission,
     408                 :                          PRUint32    aExpireType,
     409                 :                          PRInt64     aExpireTime)
     410                 : {
     411             484 :   ENSURE_NOT_CHILD_PROCESS;
     412                 : 
     413             484 :   NS_ENSURE_ARG_POINTER(aURI);
     414             484 :   NS_ENSURE_ARG_POINTER(aType);
     415             484 :   NS_ENSURE_TRUE(aExpireType == nsIPermissionManager::EXPIRE_NEVER ||
     416                 :                  aExpireType == nsIPermissionManager::EXPIRE_TIME ||
     417                 :                  aExpireType == nsIPermissionManager::EXPIRE_SESSION,
     418                 :                  NS_ERROR_INVALID_ARG);
     419                 : 
     420                 :   nsresult rv;
     421                 : 
     422                 :   // Skip addition if the permission is already expired.
     423             527 :   if (aExpireType == nsIPermissionManager::EXPIRE_TIME &&
     424              43 :       aExpireTime <= PR_Now() / 1000)
     425               1 :     return NS_OK;
     426                 : 
     427             966 :   nsCAutoString host;
     428             483 :   rv = GetHost(aURI, host);
     429             483 :   NS_ENSURE_SUCCESS(rv, rv);
     430                 : 
     431             483 :   return AddInternal(host, nsDependentCString(aType), aPermission, 0, 
     432             483 :                      aExpireType, aExpireTime, eNotify, eWriteToDB);
     433                 : }
     434                 : 
     435                 : nsresult
     436             513 : nsPermissionManager::AddInternal(const nsAFlatCString &aHost,
     437                 :                                  const nsAFlatCString &aType,
     438                 :                                  PRUint32              aPermission,
     439                 :                                  PRInt64               aID,
     440                 :                                  PRUint32              aExpireType,
     441                 :                                  PRInt64               aExpireTime,
     442                 :                                  NotifyOperationType   aNotifyOperation,
     443                 :                                  DBOperationType       aDBOperation)
     444                 : {
     445             513 :   if (!IsChildProcess()) {
     446                 :     IPC::Permission permission((aHost),
     447                 :                                (aType),
     448            1026 :                                aPermission, aExpireType, aExpireTime);
     449                 : 
     450            1026 :     nsTArray<ContentParent*> cplist;
     451             513 :     ContentParent::GetAll(cplist);
     452             513 :     for (PRUint32 i = 0; i < cplist.Length(); ++i) {
     453               0 :       ContentParent* cp = cplist[i];
     454               0 :       if (cp->NeedsPermissionsUpdate())
     455               0 :         unused << cp->SendAddPermission(permission);
     456                 :     }
     457                 :   }
     458                 : 
     459             513 :   if (!gHostArena) {
     460             218 :     gHostArena = new PLArenaPool;
     461             218 :     if (!gHostArena)
     462               0 :       return NS_ERROR_OUT_OF_MEMORY;    
     463             218 :     PL_INIT_ARENA_POOL(gHostArena, "PermissionHostArena", HOST_ARENA_SIZE);
     464                 :   }
     465                 : 
     466                 :   // look up the type index
     467             513 :   PRInt32 typeIndex = GetTypeIndex(aType.get(), true);
     468             513 :   NS_ENSURE_TRUE(typeIndex != -1, NS_ERROR_OUT_OF_MEMORY);
     469                 : 
     470                 :   // When an entry already exists, PutEntry will return that, instead
     471                 :   // of adding a new one
     472             513 :   nsHostEntry *entry = mHostTable.PutEntry(aHost.get());
     473             513 :   if (!entry) return NS_ERROR_FAILURE;
     474             513 :   if (!entry->GetKey()) {
     475               0 :     mHostTable.RawRemoveEntry(entry);
     476               0 :     return NS_ERROR_OUT_OF_MEMORY;
     477                 :   }
     478                 : 
     479                 :   // figure out the transaction type, and get any existing permission value
     480                 :   OperationType op;
     481             513 :   PRInt32 index = entry->GetPermissionIndex(typeIndex);
     482             513 :   if (index == -1) {
     483             467 :     if (aPermission == nsIPermissionManager::UNKNOWN_ACTION)
     484              17 :       op = eOperationNone;
     485                 :     else
     486             450 :       op = eOperationAdding;
     487                 : 
     488                 :   } else {
     489              46 :     nsPermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
     490                 : 
     491                 :     // remove the permission if the permission is UNKNOWN, update the
     492                 :     // permission if its value or expire type have changed OR if the time has
     493                 :     // changed and the expire type is time, otherwise, don't modify.  There's
     494                 :     // no need to modify a permission that doesn't expire with time when the
     495                 :     // only thing changed is the expire time.
     496              46 :     if (aPermission == oldPermissionEntry.mPermission && 
     497                 :         aExpireType == oldPermissionEntry.mExpireType &&
     498                 :         (aExpireType != nsIPermissionManager::EXPIRE_TIME || 
     499                 :          aExpireTime == oldPermissionEntry.mExpireTime))
     500               0 :       op = eOperationNone;
     501              46 :     else if (aPermission == nsIPermissionManager::UNKNOWN_ACTION)
     502              13 :       op = eOperationRemoving;
     503                 :     else
     504              33 :       op = eOperationChanging;
     505                 :   }
     506                 : 
     507                 :   // do the work for adding, deleting, or changing a permission:
     508                 :   // update the in-memory list, write to the db, and notify consumers.
     509                 :   PRInt64 id;
     510             513 :   switch (op) {
     511                 :   case eOperationNone:
     512                 :     {
     513                 :       // nothing to do
     514              17 :       return NS_OK;
     515                 :     }
     516                 : 
     517                 :   case eOperationAdding:
     518                 :     {
     519             450 :       if (aDBOperation == eWriteToDB) {
     520                 :         // we'll be writing to the database - generate a known unique id
     521             450 :         id = ++mLargestID;
     522                 :       } else {
     523                 :         // we're reading from the database - use the id already assigned
     524               0 :         id = aID;
     525                 :       }
     526                 : 
     527             450 :       entry->GetPermissions().AppendElement(nsPermissionEntry(typeIndex, aPermission, id, aExpireType, aExpireTime));
     528                 : 
     529             450 :       if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
     530             450 :         UpdateDB(op, mStmtInsert, id, aHost, aType, aPermission, aExpireType, aExpireTime);
     531                 : 
     532             450 :       if (aNotifyOperation == eNotify) {
     533                 :         NotifyObserversWithPermission(aHost,
     534             450 :                                       mTypeArray[typeIndex],
     535                 :                                       aPermission,
     536                 :                                       aExpireType,
     537                 :                                       aExpireTime,
     538             900 :                                       NS_LITERAL_STRING("added").get());
     539                 :       }
     540                 : 
     541             450 :       break;
     542                 :     }
     543                 : 
     544                 :   case eOperationRemoving:
     545                 :     {
     546              13 :       nsPermissionEntry oldPermissionEntry = entry->GetPermissions()[index];
     547              13 :       id = oldPermissionEntry.mID;
     548              13 :       entry->GetPermissions().RemoveElementAt(index);
     549                 : 
     550                 :       // If no more types are present, remove the entry
     551              13 :       if (entry->GetPermissions().IsEmpty())
     552               9 :         mHostTable.RawRemoveEntry(entry);
     553                 : 
     554              13 :       if (aDBOperation == eWriteToDB)
     555              26 :         UpdateDB(op, mStmtDelete, id, EmptyCString(), EmptyCString(), 0, 
     556              26 :                  nsIPermissionManager::EXPIRE_NEVER, 0);
     557                 : 
     558              13 :       if (aNotifyOperation == eNotify) {
     559                 :         NotifyObserversWithPermission(aHost,
     560              13 :                                       mTypeArray[typeIndex],
     561                 :                                       oldPermissionEntry.mPermission,
     562                 :                                       oldPermissionEntry.mExpireType,
     563                 :                                       oldPermissionEntry.mExpireTime,
     564              26 :                                       NS_LITERAL_STRING("deleted").get());
     565                 :       }
     566                 : 
     567              13 :       break;
     568                 :     }
     569                 : 
     570                 :   case eOperationChanging:
     571                 :     {
     572              33 :       id = entry->GetPermissions()[index].mID;
     573              33 :       entry->GetPermissions()[index].mPermission = aPermission;
     574                 : 
     575              33 :       if (aDBOperation == eWriteToDB && aExpireType != nsIPermissionManager::EXPIRE_SESSION)
     576              33 :         UpdateDB(op, mStmtUpdate, id, EmptyCString(), EmptyCString(), aPermission, aExpireType, aExpireTime);
     577                 : 
     578              33 :       if (aNotifyOperation == eNotify) {
     579                 :         NotifyObserversWithPermission(aHost,
     580              33 :                                       mTypeArray[typeIndex],
     581                 :                                       aPermission,
     582                 :                                       aExpireType,
     583                 :                                       aExpireTime,
     584              66 :                                       NS_LITERAL_STRING("changed").get());
     585                 :       }
     586                 : 
     587              33 :       break;
     588                 :     }
     589                 :   }
     590                 : 
     591             496 :   return NS_OK;
     592                 : }
     593                 : 
     594                 : NS_IMETHODIMP
     595              30 : nsPermissionManager::Remove(const nsACString &aHost,
     596                 :                             const char       *aType)
     597                 : {
     598              30 :   ENSURE_NOT_CHILD_PROCESS;
     599                 : 
     600              30 :   NS_ENSURE_ARG_POINTER(aType);
     601                 : 
     602                 :   // AddInternal() handles removal, just let it do the work
     603              30 :   return AddInternal(PromiseFlatCString(aHost),
     604              30 :                      nsDependentCString(aType),
     605                 :                      nsIPermissionManager::UNKNOWN_ACTION,
     606                 :                      0,
     607                 :                      nsIPermissionManager::EXPIRE_NEVER,
     608                 :                      0,
     609                 :                      eNotify,
     610              30 :                      eWriteToDB);
     611                 : }
     612                 : 
     613                 : NS_IMETHODIMP
     614               8 : nsPermissionManager::RemoveAll()
     615                 : {
     616               8 :   ENSURE_NOT_CHILD_PROCESS;
     617                 : 
     618               8 :   nsresult rv = RemoveAllInternal();
     619               8 :   NotifyObservers(nsnull, NS_LITERAL_STRING("cleared").get());
     620               8 :   return rv;
     621                 : }
     622                 : 
     623                 : void
     624             300 : nsPermissionManager::CloseDB()
     625                 : {
     626                 :   // Null the statements, this will finalize them.
     627             300 :   mStmtInsert = nsnull;
     628             300 :   mStmtDelete = nsnull;
     629             300 :   mStmtUpdate = nsnull;
     630             300 :   if (mDBConn) {
     631             576 :     mozilla::DebugOnly<nsresult> rv = mDBConn->Close();
     632             288 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
     633             288 :     mDBConn = nsnull;
     634                 :   }
     635             300 : }
     636                 : 
     637                 : nsresult
     638               8 : nsPermissionManager::RemoveAllInternal()
     639                 : {
     640               8 :   RemoveAllFromMemory();
     641                 : 
     642                 :   // clear the db
     643               8 :   if (mDBConn) {
     644               7 :     nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_hosts"));
     645               7 :     if (NS_FAILED(rv)) {
     646               1 :       CloseDB();
     647               1 :       rv = InitDB(true);
     648               1 :       return rv;
     649                 :     }
     650                 :   }
     651                 : 
     652               7 :   return NS_OK;
     653                 : }
     654                 : 
     655                 : NS_IMETHODIMP
     656            5085 : nsPermissionManager::TestExactPermission(nsIURI     *aURI,
     657                 :                                          const char *aType,
     658                 :                                          PRUint32   *aPermission)
     659                 : {
     660            5085 :   return CommonTestPermission(aURI, aType, aPermission, true);
     661                 : }
     662                 : 
     663                 : NS_IMETHODIMP
     664           39192 : nsPermissionManager::TestPermission(nsIURI     *aURI,
     665                 :                                     const char *aType,
     666                 :                                     PRUint32   *aPermission)
     667                 : {
     668           39192 :   return CommonTestPermission(aURI, aType, aPermission, false);
     669                 : }
     670                 : 
     671                 : nsresult
     672           44277 : nsPermissionManager::CommonTestPermission(nsIURI     *aURI,
     673                 :                                           const char *aType,
     674                 :                                           PRUint32   *aPermission,
     675                 :                                           bool        aExactHostMatch)
     676                 : {
     677           44277 :   NS_ENSURE_ARG_POINTER(aURI);
     678           44277 :   NS_ENSURE_ARG_POINTER(aType);
     679                 : 
     680                 :   // set the default
     681           44277 :   *aPermission = nsIPermissionManager::UNKNOWN_ACTION;
     682                 : 
     683           88554 :   nsCAutoString host;
     684           44277 :   nsresult rv = GetHost(aURI, host);
     685                 :   // No host doesn't mean an error. Just return the default. Unless this is
     686                 :   // a file uri. In that case use a magic host.
     687           44277 :   if (NS_FAILED(rv)) {
     688                 :     bool isFile;
     689              25 :     rv = aURI->SchemeIs("file", &isFile);
     690              25 :     NS_ENSURE_SUCCESS(rv, rv);
     691              25 :     if (isFile) {
     692               7 :       host.AssignLiteral("<file>");
     693                 :     }
     694                 :     else {
     695              18 :       return NS_OK;
     696                 :     }
     697                 :   }
     698                 :   
     699           44259 :   PRInt32 typeIndex = GetTypeIndex(aType, false);
     700                 :   // If type == -1, the type isn't known,
     701                 :   // so just return NS_OK
     702           44259 :   if (typeIndex == -1) return NS_OK;
     703                 : 
     704             304 :   nsHostEntry *entry = GetHostEntry(host, typeIndex, aExactHostMatch);
     705             304 :   if (entry)
     706              39 :     *aPermission = entry->GetPermission(typeIndex).mPermission;
     707                 : 
     708             304 :   return NS_OK;
     709                 : }
     710                 : 
     711                 : // Get hostentry for given host string and permission type.
     712                 : // walk up the domain if needed.
     713                 : // return null if nothing found.
     714                 : // Also accepts host on the format "<foo>". This will perform an exact match
     715                 : // lookup as the string doesn't contain any dots.
     716                 : nsHostEntry *
     717             304 : nsPermissionManager::GetHostEntry(const nsAFlatCString &aHost,
     718                 :                                   PRUint32              aType,
     719                 :                                   bool                  aExactHostMatch)
     720                 : {
     721             304 :   PRUint32 offset = 0;
     722                 :   nsHostEntry *entry;
     723             304 :   PRInt64 now = PR_Now() / 1000;
     724                 : 
     725             568 :   do {
     726             676 :     entry = mHostTable.GetEntry(aHost.get() + offset);
     727             676 :     if (entry) {
     728              40 :       nsPermissionEntry permEntry = entry->GetPermission(aType);
     729                 : 
     730                 :       // if the entry is expired, remove and keep looking for others.
     731              40 :       if (permEntry.mExpireType == nsIPermissionManager::EXPIRE_TIME &&
     732                 :           permEntry.mExpireTime <= now)
     733               1 :         Remove(aHost, mTypeArray[aType].get());
     734              39 :       else if (permEntry.mPermission != nsIPermissionManager::UNKNOWN_ACTION)
     735              39 :         break;
     736                 : 
     737                 :       // reset entry, to be able to return null on failure
     738               1 :       entry = nsnull;
     739                 :     }
     740             637 :     if (aExactHostMatch)
     741              69 :       break; // do not try super domains
     742                 : 
     743             568 :     offset = aHost.FindChar('.', offset) + 1;
     744                 : 
     745                 :   // walk up the domaintree (we stop as soon as we find a match,
     746                 :   // which will be the most specific domain we have an entry for).
     747                 :   } while (offset > 0);
     748             304 :   return entry;
     749                 : }
     750                 : 
     751                 : // helper struct for passing arguments into hash enumeration callback.
     752                 : struct nsGetEnumeratorData
     753                 : {
     754              66 :   nsGetEnumeratorData(nsCOMArray<nsIPermission> *aArray, const nsTArray<nsCString> *aTypes)
     755                 :    : array(aArray)
     756              66 :    , types(aTypes) {}
     757                 : 
     758                 :   nsCOMArray<nsIPermission> *array;
     759                 :   const nsTArray<nsCString> *types;
     760                 : };
     761                 : 
     762                 : static PLDHashOperator
     763              11 : AddPermissionsToList(nsHostEntry *entry, void *arg)
     764                 : {
     765              11 :   nsGetEnumeratorData *data = static_cast<nsGetEnumeratorData *>(arg);
     766                 : 
     767              24 :   for (PRUint32 i = 0; i < entry->GetPermissions().Length(); ++i) {
     768              13 :     nsPermissionEntry &permEntry = entry->GetPermissions()[i];
     769                 : 
     770              13 :     nsPermission *perm = new nsPermission(entry->GetHost(), 
     771              13 :                                           data->types->ElementAt(permEntry.mType),
     772                 :                                           permEntry.mPermission,
     773                 :                                           permEntry.mExpireType,
     774              39 :                                           permEntry.mExpireTime);
     775                 : 
     776              13 :     data->array->AppendObject(perm);
     777                 :   }
     778                 : 
     779              11 :   return PL_DHASH_NEXT;
     780                 : }
     781                 : 
     782              66 : NS_IMETHODIMP nsPermissionManager::GetEnumerator(nsISimpleEnumerator **aEnum)
     783                 : {
     784                 :   // roll an nsCOMArray of all our permissions, then hand out an enumerator
     785             132 :   nsCOMArray<nsIPermission> array;
     786              66 :   nsGetEnumeratorData data(&array, &mTypeArray);
     787                 : 
     788              66 :   mHostTable.EnumerateEntries(AddPermissionsToList, &data);
     789                 : 
     790              66 :   return NS_NewArrayEnumerator(aEnum, array);
     791                 : }
     792                 : 
     793             299 : NS_IMETHODIMP nsPermissionManager::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *someData)
     794                 : {
     795             299 :   ENSURE_NOT_CHILD_PROCESS;
     796                 : 
     797             299 :   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     798                 :     // The profile is about to change,
     799                 :     // or is going away because the application is shutting down.
     800             299 :     if (!nsCRT::strcmp(someData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
     801                 :       // clear the permissions file
     802               0 :       RemoveAllInternal();
     803                 :     } else {
     804             299 :       RemoveAllFromMemory();
     805                 :     }
     806             299 :     CloseDB();
     807                 :   }
     808               0 :   else if (!nsCRT::strcmp(aTopic, "profile-do-change")) {
     809                 :     // the profile has already changed; init the db from the new location
     810               0 :     InitDB(false);
     811                 :   }
     812                 : 
     813             299 :   return NS_OK;
     814                 : }
     815                 : 
     816                 : //*****************************************************************************
     817                 : //*** nsPermissionManager private methods
     818                 : //*****************************************************************************
     819                 : 
     820                 : nsresult
     821             705 : nsPermissionManager::RemoveAllFromMemory()
     822                 : {
     823             705 :   mLargestID = 0;
     824             705 :   mTypeArray.Clear();
     825             705 :   mHostTable.Clear();
     826             705 :   if (gHostArena) {
     827             218 :     PL_FinishArenaPool(gHostArena);
     828             218 :     delete gHostArena;
     829                 :   }
     830             705 :   gHostArena = nsnull;
     831             705 :   return NS_OK;
     832                 : }
     833                 : 
     834                 : // Returns -1 on failure
     835                 : PRInt32
     836           44772 : nsPermissionManager::GetTypeIndex(const char *aType,
     837                 :                                   bool        aAdd)
     838                 : {
     839           49829 :   for (PRUint32 i = 0; i < mTypeArray.Length(); ++i)
     840            5642 :     if (mTypeArray[i].Equals(aType))
     841             585 :       return i;
     842                 : 
     843           44187 :   if (!aAdd) {
     844                 :     // Not found, but that is ok - we were just looking.
     845           43955 :     return -1;
     846                 :   }
     847                 : 
     848                 :   // This type was not registered before.
     849                 :   // append it to the array, without copy-constructing the string
     850             232 :   nsCString *elem = mTypeArray.AppendElement();
     851             232 :   if (!elem)
     852               0 :     return -1;
     853                 : 
     854             232 :   elem->Assign(aType);
     855             232 :   return mTypeArray.Length() - 1;
     856                 : }
     857                 : 
     858                 : // wrapper function for mangling (host,type,perm,expireType,expireTime)
     859                 : // set into an nsIPermission.
     860                 : void
     861             496 : nsPermissionManager::NotifyObserversWithPermission(const nsACString &aHost,
     862                 :                                                    const nsCString  &aType,
     863                 :                                                    PRUint32          aPermission,
     864                 :                                                    PRUint32          aExpireType,
     865                 :                                                    PRInt64           aExpireTime,
     866                 :                                                    const PRUnichar  *aData)
     867                 : {
     868                 :   nsCOMPtr<nsIPermission> permission =
     869             992 :     new nsPermission(aHost, aType, aPermission, aExpireType, aExpireTime);
     870             496 :   if (permission)
     871             496 :     NotifyObservers(permission, aData);
     872             496 : }
     873                 : 
     874                 : // notify observers that the permission list changed. there are four possible
     875                 : // values for aData:
     876                 : // "deleted" means a permission was deleted. aPermission is the deleted permission.
     877                 : // "added"   means a permission was added. aPermission is the added permission.
     878                 : // "changed" means a permission was altered. aPermission is the new permission.
     879                 : // "cleared" means the entire permission list was cleared. aPermission is null.
     880                 : void
     881             504 : nsPermissionManager::NotifyObservers(nsIPermission   *aPermission,
     882                 :                                      const PRUnichar *aData)
     883                 : {
     884             504 :   if (mObserverService)
     885             504 :     mObserverService->NotifyObservers(aPermission,
     886                 :                                       kPermissionChangeNotification,
     887             504 :                                       aData);
     888             504 : }
     889                 : 
     890                 : nsresult
     891               0 : nsPermissionManager::Read()
     892                 : {
     893               0 :   ENSURE_NOT_CHILD_PROCESS;
     894                 : 
     895                 :   nsresult rv;
     896                 : 
     897                 :   // delete expired permissions before we read in the db
     898                 :   {
     899                 :     // this deletion has its own scope so the write lock is released when done.
     900               0 :     nsCOMPtr<mozIStorageStatement> stmtDeleteExpired;
     901               0 :     rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
     902                 :           "DELETE FROM moz_hosts WHERE expireType = ?1 AND expireTime <= ?2"),
     903               0 :           getter_AddRefs(stmtDeleteExpired));
     904               0 :     NS_ENSURE_SUCCESS(rv, rv);
     905                 : 
     906               0 :     rv = stmtDeleteExpired->BindInt32ByIndex(0, nsIPermissionManager::EXPIRE_TIME);
     907               0 :     NS_ENSURE_SUCCESS(rv, rv);
     908                 : 
     909               0 :     rv = stmtDeleteExpired->BindInt64ByIndex(1, PR_Now() / 1000);
     910               0 :     NS_ENSURE_SUCCESS(rv, rv);
     911                 : 
     912                 :     bool hasResult;
     913               0 :     rv = stmtDeleteExpired->ExecuteStep(&hasResult);
     914               0 :     NS_ENSURE_SUCCESS(rv, rv);
     915                 :   }
     916                 : 
     917               0 :   nsCOMPtr<mozIStorageStatement> stmt;
     918               0 :   rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
     919                 :     "SELECT id, host, type, permission, expireType, expireTime "
     920               0 :     "FROM moz_hosts"), getter_AddRefs(stmt));
     921               0 :   NS_ENSURE_SUCCESS(rv, rv);
     922                 : 
     923                 :   PRInt64 id;
     924               0 :   nsCAutoString host, type;
     925                 :   PRUint32 permission;
     926                 :   PRUint32 expireType;
     927                 :   PRInt64 expireTime;
     928                 :   bool hasResult;
     929               0 :   while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
     930                 :     // explicitly set our entry id counter for use in AddInternal(),
     931                 :     // and keep track of the largest id so we know where to pick up.
     932               0 :     id = stmt->AsInt64(0);
     933               0 :     if (id > mLargestID)
     934               0 :       mLargestID = id;
     935                 : 
     936               0 :     rv = stmt->GetUTF8String(1, host);
     937               0 :     NS_ENSURE_SUCCESS(rv, rv);
     938                 : 
     939               0 :     rv = stmt->GetUTF8String(2, type);
     940               0 :     NS_ENSURE_SUCCESS(rv, rv);
     941                 : 
     942               0 :     permission = stmt->AsInt32(3);
     943               0 :     expireType = stmt->AsInt32(4);
     944                 : 
     945                 :     // convert into PRInt64 value (milliseconds)
     946               0 :     expireTime = stmt->AsInt64(5);
     947                 : 
     948                 :     rv = AddInternal(host, type, permission, id, expireType, expireTime,
     949               0 :                      eDontNotify, eNoDBOperation);
     950               0 :     NS_ENSURE_SUCCESS(rv, rv);
     951                 :   }
     952                 : 
     953               0 :   return NS_OK;
     954                 : }
     955                 : 
     956                 : static const char kMatchTypeHost[] = "host";
     957                 : 
     958                 : nsresult
     959             288 : nsPermissionManager::Import()
     960                 : {
     961             288 :   ENSURE_NOT_CHILD_PROCESS;
     962                 : 
     963                 :   nsresult rv;
     964                 : 
     965             576 :   nsCOMPtr<nsIFile> permissionsFile;
     966             288 :   rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(permissionsFile));
     967             288 :   if (NS_FAILED(rv)) return rv;
     968                 : 
     969             288 :   rv = permissionsFile->AppendNative(NS_LITERAL_CSTRING(kHostpermFileName));
     970             288 :   NS_ENSURE_SUCCESS(rv, rv);
     971                 : 
     972             576 :   nsCOMPtr<nsIInputStream> fileInputStream;
     973             288 :   rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream),
     974             288 :                                   permissionsFile);
     975             288 :   if (NS_FAILED(rv)) return rv;
     976                 : 
     977               2 :   nsCOMPtr<nsILineInputStream> lineInputStream = do_QueryInterface(fileInputStream, &rv);
     978               1 :   NS_ENSURE_SUCCESS(rv, rv);
     979                 : 
     980                 :   // start a transaction on the storage db, to optimize insertions.
     981                 :   // transaction will automically commit on completion
     982               2 :   mozStorageTransaction transaction(mDBConn, true);
     983                 : 
     984                 :   /* format is:
     985                 :    * matchtype \t type \t permission \t host
     986                 :    * Only "host" is supported for matchtype
     987                 :    * type is a string that identifies the type of permission (e.g. "cookie")
     988                 :    * permission is an integer between 1 and 15
     989                 :    */
     990                 : 
     991               2 :   nsCAutoString buffer;
     992               1 :   bool isMore = true;
     993               3 :   while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
     994               1 :     if (buffer.IsEmpty() || buffer.First() == '#') {
     995               1 :       continue;
     996                 :     }
     997                 : 
     998               0 :     nsTArray<nsCString> lineArray;
     999                 : 
    1000                 :     // Split the line at tabs
    1001               0 :     ParseString(buffer, '\t', lineArray);
    1002                 :     
    1003               0 :     if (lineArray[0].EqualsLiteral(kMatchTypeHost) &&
    1004               0 :         lineArray.Length() == 4) {
    1005                 :       
    1006                 :       PRInt32 error;
    1007               0 :       PRUint32 permission = lineArray[2].ToInteger(&error);
    1008               0 :       if (error)
    1009               0 :         continue;
    1010                 : 
    1011                 :       // hosts might be encoded in UTF8; switch them to ACE to be consistent
    1012               0 :       if (!IsASCII(lineArray[3])) {
    1013               0 :         rv = NormalizeToACE(lineArray[3]);
    1014               0 :         if (NS_FAILED(rv))
    1015               0 :           continue;
    1016                 :       }
    1017                 : 
    1018               0 :       rv = AddInternal(lineArray[3], lineArray[1], permission, 0, 
    1019               0 :                        nsIPermissionManager::EXPIRE_NEVER, 0, eDontNotify, eWriteToDB);
    1020               0 :       NS_ENSURE_SUCCESS(rv, rv);
    1021                 :     }
    1022                 :   }
    1023                 : 
    1024                 :   // we're done importing - delete the old file
    1025               1 :   permissionsFile->Remove(false);
    1026                 : 
    1027               1 :   return NS_OK;
    1028                 : }
    1029                 : 
    1030                 : nsresult
    1031               0 : nsPermissionManager::NormalizeToACE(nsCString &aHost)
    1032                 : {
    1033                 :   // lazily init the IDN service
    1034               0 :   if (!mIDNService) {
    1035                 :     nsresult rv;
    1036               0 :     mIDNService = do_GetService(NS_IDNSERVICE_CONTRACTID, &rv);
    1037               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1038                 :   }
    1039                 : 
    1040               0 :   return mIDNService->ConvertUTF8toACE(aHost, aHost);
    1041                 : }
    1042                 : 
    1043                 : nsresult
    1044           44760 : nsPermissionManager::GetHost(nsIURI *aURI, nsACString &aResult)
    1045                 : {
    1046           89520 :   nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
    1047           44760 :   if (!innerURI) return NS_ERROR_FAILURE;
    1048                 : 
    1049           44760 :   nsresult rv = innerURI->GetAsciiHost(aResult);
    1050                 : 
    1051           44760 :   if (NS_FAILED(rv) || aResult.IsEmpty())
    1052              25 :     return NS_ERROR_UNEXPECTED;
    1053                 : 
    1054           44735 :   return NS_OK;
    1055                 : }
    1056                 : 
    1057                 : void
    1058             496 : nsPermissionManager::UpdateDB(OperationType         aOp,
    1059                 :                               mozIStorageStatement* aStmt,
    1060                 :                               PRInt64               aID,
    1061                 :                               const nsACString     &aHost,
    1062                 :                               const nsACString     &aType,
    1063                 :                               PRUint32              aPermission,
    1064                 :                               PRUint32              aExpireType,
    1065                 :                               PRInt64               aExpireTime)
    1066                 : {
    1067             496 :   ENSURE_NOT_CHILD_PROCESS_NORET;
    1068                 : 
    1069                 :   nsresult rv;
    1070                 : 
    1071                 :   // no statement is ok - just means we don't have a profile
    1072             496 :   if (!aStmt)
    1073              22 :     return;
    1074                 : 
    1075             474 :   switch (aOp) {
    1076                 :   case eOperationAdding:
    1077                 :     {
    1078             434 :       rv = aStmt->BindInt64ByIndex(0, aID);
    1079             434 :       if (NS_FAILED(rv)) break;
    1080                 : 
    1081             434 :       rv = aStmt->BindUTF8StringByIndex(1, aHost);
    1082             434 :       if (NS_FAILED(rv)) break;
    1083                 :       
    1084             434 :       rv = aStmt->BindUTF8StringByIndex(2, aType);
    1085             434 :       if (NS_FAILED(rv)) break;
    1086                 : 
    1087             434 :       rv = aStmt->BindInt32ByIndex(3, aPermission);
    1088             434 :       if (NS_FAILED(rv)) break;
    1089                 : 
    1090             434 :       rv = aStmt->BindInt32ByIndex(4, aExpireType);
    1091             434 :       if (NS_FAILED(rv)) break;
    1092                 : 
    1093             434 :       rv = aStmt->BindInt64ByIndex(5, aExpireTime);
    1094             434 :       break;
    1095                 :     }
    1096                 : 
    1097                 :   case eOperationRemoving:
    1098                 :     {
    1099               7 :       rv = aStmt->BindInt64ByIndex(0, aID);
    1100               7 :       break;
    1101                 :     }
    1102                 : 
    1103                 :   case eOperationChanging:
    1104                 :     {
    1105              33 :       rv = aStmt->BindInt64ByIndex(0, aID);
    1106              33 :       if (NS_FAILED(rv)) break;
    1107                 : 
    1108              33 :       rv = aStmt->BindInt32ByIndex(1, aPermission);
    1109              33 :       if (NS_FAILED(rv)) break;
    1110                 : 
    1111              33 :       rv = aStmt->BindInt32ByIndex(2, aExpireType);
    1112              33 :       if (NS_FAILED(rv)) break;
    1113                 : 
    1114              33 :       rv = aStmt->BindInt64ByIndex(3, aExpireTime);
    1115              33 :       break;
    1116                 :     }
    1117                 : 
    1118                 :   default:
    1119                 :     {
    1120               0 :       NS_NOTREACHED("need a valid operation in UpdateDB()!");
    1121               0 :       rv = NS_ERROR_UNEXPECTED;
    1122               0 :       break;
    1123                 :     }
    1124                 :   }
    1125                 : 
    1126             474 :   if (NS_SUCCEEDED(rv)) {
    1127                 :     bool hasResult;
    1128             474 :     rv = aStmt->ExecuteStep(&hasResult);
    1129             474 :     aStmt->Reset();
    1130                 :   }
    1131                 : 
    1132             474 :   if (NS_FAILED(rv))
    1133               0 :     NS_WARNING("db change failed!");
    1134                 : }
    1135                 : 

Generated by: LCOV version 1.7