LCOV - code coverage report
Current view: directory - toolkit/components/places - Helpers.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 180 157 87.2 %
Date: 2012-06-02 Functions: 33 30 90.9 %

       1                 : /* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
       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 Places code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * the Mozilla Foundation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "Helpers.h"
      40                 : #include "mozIStorageError.h"
      41                 : #include "plbase64.h"
      42                 : #include "prio.h"
      43                 : #include "nsString.h"
      44                 : #include "nsNavHistory.h"
      45                 : #include "mozilla/Services.h"
      46                 : #if defined(XP_OS2)
      47                 : #include "nsIRandomGenerator.h"
      48                 : #endif
      49                 : #include "nsContentUtils.h"
      50                 : 
      51                 : // The length of guids that are used by history and bookmarks.
      52                 : #define GUID_LENGTH 12
      53                 : 
      54                 : namespace mozilla {
      55                 : namespace places {
      56                 : 
      57                 : ////////////////////////////////////////////////////////////////////////////////
      58                 : //// AsyncStatementCallback
      59                 : 
      60           25740 : NS_IMPL_ISUPPORTS1(
      61                 :   AsyncStatementCallback
      62                 : , mozIStorageStatementCallback
      63                 : )
      64                 : 
      65                 : NS_IMETHODIMP
      66               0 : AsyncStatementCallback::HandleResult(mozIStorageResultSet *aResultSet)
      67                 : {
      68               0 :   NS_ABORT_IF_FALSE(false, "Was not expecting a resultset, but got it.");
      69               0 :   return NS_OK;
      70                 : }
      71                 : 
      72                 : NS_IMETHODIMP
      73            1252 : AsyncStatementCallback::HandleCompletion(PRUint16 aReason)
      74                 : {
      75            1252 :   return NS_OK;
      76                 : }
      77                 : 
      78                 : NS_IMETHODIMP
      79               0 : AsyncStatementCallback::HandleError(mozIStorageError *aError)
      80                 : {
      81                 : #ifdef DEBUG
      82                 :   PRInt32 result;
      83               0 :   nsresult rv = aError->GetResult(&result);
      84               0 :   NS_ENSURE_SUCCESS(rv, rv);
      85               0 :   nsCAutoString message;
      86               0 :   rv = aError->GetMessage(message);
      87               0 :   NS_ENSURE_SUCCESS(rv, rv);
      88                 : 
      89               0 :   nsCAutoString warnMsg;
      90               0 :   warnMsg.Append("An error occurred while executing an async statement: ");
      91               0 :   warnMsg.AppendInt(result);
      92               0 :   warnMsg.Append(" ");
      93               0 :   warnMsg.Append(message);
      94               0 :   NS_WARNING(warnMsg.get());
      95                 : #endif
      96                 : 
      97               0 :   return NS_OK;
      98                 : }
      99                 : 
     100                 : #define URI_TO_URLCSTRING(uri, spec) \
     101                 :   nsCAutoString spec; \
     102                 :   if (NS_FAILED(aURI->GetSpec(spec))) { \
     103                 :     return NS_ERROR_UNEXPECTED; \
     104                 :   }
     105                 : 
     106                 : // Bind URI to statement by index.
     107                 : nsresult // static
     108               0 : URIBinder::Bind(mozIStorageStatement* aStatement,
     109                 :                 PRInt32 aIndex,
     110                 :                 nsIURI* aURI)
     111                 : {
     112               0 :   NS_ASSERTION(aStatement, "Must have non-null statement");
     113               0 :   NS_ASSERTION(aURI, "Must have non-null uri");
     114                 : 
     115               0 :   URI_TO_URLCSTRING(aURI, spec);
     116               0 :   return URIBinder::Bind(aStatement, aIndex, spec);
     117                 : }
     118                 : 
     119                 : // Statement URLCString to statement by index.
     120                 : nsresult // static
     121             149 : URIBinder::Bind(mozIStorageStatement* aStatement,
     122                 :                 PRInt32 index,
     123                 :                 const nsACString& aURLString)
     124                 : {
     125             149 :   NS_ASSERTION(aStatement, "Must have non-null statement");
     126                 :   return aStatement->BindUTF8StringByIndex(
     127             149 :     index, StringHead(aURLString, URI_LENGTH_MAX)
     128             149 :   );
     129                 : }
     130                 : 
     131                 : // Bind URI to statement by name.
     132                 : nsresult // static
     133            7944 : URIBinder::Bind(mozIStorageStatement* aStatement,
     134                 :                 const nsACString& aName,
     135                 :                 nsIURI* aURI)
     136                 : {
     137            7944 :   NS_ASSERTION(aStatement, "Must have non-null statement");
     138            7944 :   NS_ASSERTION(aURI, "Must have non-null uri");
     139                 : 
     140           15888 :   URI_TO_URLCSTRING(aURI, spec);
     141            7944 :   return URIBinder::Bind(aStatement, aName, spec);
     142                 : }
     143                 : 
     144                 : // Bind URLCString to statement by name.
     145                 : nsresult // static
     146           10022 : URIBinder::Bind(mozIStorageStatement* aStatement,
     147                 :                 const nsACString& aName,
     148                 :                 const nsACString& aURLString)
     149                 : {
     150           10022 :   NS_ASSERTION(aStatement, "Must have non-null statement");
     151                 :   return aStatement->BindUTF8StringByName(
     152           10022 :     aName, StringHead(aURLString, URI_LENGTH_MAX)
     153           10022 :   );
     154                 : }
     155                 : 
     156                 : // Bind URI to params by index.
     157                 : nsresult // static
     158             342 : URIBinder::Bind(mozIStorageBindingParams* aParams,
     159                 :                 PRInt32 aIndex,
     160                 :                 nsIURI* aURI)
     161                 : {
     162             342 :   NS_ASSERTION(aParams, "Must have non-null statement");
     163             342 :   NS_ASSERTION(aURI, "Must have non-null uri");
     164                 : 
     165             684 :   URI_TO_URLCSTRING(aURI, spec);
     166             342 :   return URIBinder::Bind(aParams, aIndex, spec);
     167                 : }
     168                 : 
     169                 : // Bind URLCString to params by index.
     170                 : nsresult // static
     171             342 : URIBinder::Bind(mozIStorageBindingParams* aParams,
     172                 :                 PRInt32 index,
     173                 :                 const nsACString& aURLString)
     174                 : {
     175             342 :   NS_ASSERTION(aParams, "Must have non-null statement");
     176                 :   return aParams->BindUTF8StringByIndex(
     177             342 :     index, StringHead(aURLString, URI_LENGTH_MAX)
     178             342 :   );
     179                 : }
     180                 : 
     181                 : // Bind URI to params by name.
     182                 : nsresult // static
     183              81 : URIBinder::Bind(mozIStorageBindingParams* aParams,
     184                 :                 const nsACString& aName,
     185                 :                 nsIURI* aURI)
     186                 : {
     187              81 :   NS_ASSERTION(aParams, "Must have non-null params array");
     188              81 :   NS_ASSERTION(aURI, "Must have non-null uri");
     189                 : 
     190             162 :   URI_TO_URLCSTRING(aURI, spec);
     191              81 :   return URIBinder::Bind(aParams, aName, spec);
     192                 : }
     193                 : 
     194                 : // Bind URLCString to params by name.
     195                 : nsresult // static
     196            1546 : URIBinder::Bind(mozIStorageBindingParams* aParams,
     197                 :                 const nsACString& aName,
     198                 :                 const nsACString& aURLString)
     199                 : {
     200            1546 :   NS_ASSERTION(aParams, "Must have non-null params array");
     201                 : 
     202                 :   nsresult rv = aParams->BindUTF8StringByName(
     203            1546 :     aName, StringHead(aURLString, URI_LENGTH_MAX)
     204            1546 :   );
     205            1546 :   NS_ENSURE_SUCCESS(rv, rv);
     206            1546 :   return NS_OK;
     207                 : }
     208                 : 
     209                 : #undef URI_TO_URLCSTRING
     210                 : 
     211                 : nsresult
     212            1757 : GetReversedHostname(nsIURI* aURI, nsString& aRevHost)
     213                 : {
     214            3514 :   nsCAutoString forward8;
     215            1757 :   nsresult rv = aURI->GetHost(forward8);
     216                 :   // Not all URIs have a host.
     217            1757 :   if (NS_FAILED(rv))
     218             148 :     return rv;
     219                 : 
     220                 :   // can't do reversing in UTF8, better use 16-bit chars
     221            1609 :   GetReversedHostname(NS_ConvertUTF8toUTF16(forward8), aRevHost);
     222            1609 :   return NS_OK;
     223                 : }
     224                 : 
     225                 : void
     226            1755 : GetReversedHostname(const nsString& aForward, nsString& aRevHost)
     227                 : {
     228            1755 :   ReverseString(aForward, aRevHost);
     229            1755 :   aRevHost.Append(PRUnichar('.'));
     230            1755 : }
     231                 : 
     232                 : void
     233           23363 : ReverseString(const nsString& aInput, nsString& aReversed)
     234                 : {
     235           23363 :   aReversed.Truncate(0);
     236          292014 :   for (PRInt32 i = aInput.Length() - 1; i >= 0; i--) {
     237          268651 :     aReversed.Append(aInput[i]);
     238                 :   }
     239           23363 : }
     240                 : 
     241                 : static
     242                 : nsresult
     243            5336 : Base64urlEncode(const PRUint8* aBytes,
     244                 :                 PRUint32 aNumBytes,
     245                 :                 nsCString& _result)
     246                 : {
     247                 :   // SetLength does not set aside space for NULL termination.  PL_Base64Encode
     248                 :   // will not NULL terminate, however, nsCStrings must be NULL terminated.  As a
     249                 :   // result, we set the capacity to be one greater than what we need, and the
     250                 :   // length to our desired length.
     251            5336 :   PRUint32 length = (aNumBytes + 2) / 3 * 4; // +2 due to integer math.
     252            5336 :   NS_ENSURE_TRUE(_result.SetCapacity(length + 1), NS_ERROR_OUT_OF_MEMORY);
     253            5336 :   _result.SetLength(length);
     254                 :   (void)PL_Base64Encode(reinterpret_cast<const char*>(aBytes), aNumBytes,
     255            5336 :                         _result.BeginWriting());
     256                 : 
     257                 :   // base64url encoding is defined in RFC 4648.  It replaces the last two
     258                 :   // alphabet characters of base64 encoding with '-' and '_' respectively.
     259            5336 :   _result.ReplaceChar('+', '-');
     260            5336 :   _result.ReplaceChar('/', '_');
     261            5336 :   return NS_OK;
     262                 : }
     263                 : 
     264                 : #ifdef XP_WIN
     265                 : // Included here because windows.h conflicts with the use of mozIStorageError
     266                 : // above.
     267                 : #include <windows.h>
     268                 : #include <wincrypt.h>
     269                 : #endif
     270                 : 
     271                 : static
     272                 : nsresult
     273            5336 : GenerateRandomBytes(PRUint32 aSize,
     274                 :                     PRUint8* _buffer)
     275                 : {
     276                 :   // On Windows, we'll use its built-in cryptographic API.
     277                 : #if defined(XP_WIN)
     278                 :   HCRYPTPROV cryptoProvider;
     279                 :   BOOL rc = CryptAcquireContext(&cryptoProvider, 0, 0, PROV_RSA_FULL,
     280                 :                                 CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
     281                 :   if (rc) {
     282                 :     rc = CryptGenRandom(cryptoProvider, aSize, _buffer);
     283                 :     (void)CryptReleaseContext(cryptoProvider, 0);
     284                 :   }
     285                 :   return rc ? NS_OK : NS_ERROR_FAILURE;
     286                 : 
     287                 :   // On Unix, we'll just read in from /dev/urandom.
     288                 : #elif defined(XP_UNIX)
     289            5336 :   NS_ENSURE_ARG_MAX(aSize, PR_INT32_MAX);
     290            5336 :   PRFileDesc* urandom = PR_Open("/dev/urandom", PR_RDONLY, 0);
     291            5336 :   nsresult rv = NS_ERROR_FAILURE;
     292            5336 :   if (urandom) {
     293            5336 :     PRInt32 bytesRead = PR_Read(urandom, _buffer, aSize);
     294            5336 :     if (bytesRead == static_cast<PRInt32>(aSize)) {
     295            5336 :       rv = NS_OK;
     296                 :     }
     297            5336 :     (void)PR_Close(urandom);
     298                 :   }
     299            5336 :   return rv;
     300                 : #elif defined(XP_OS2)
     301                 :   nsCOMPtr<nsIRandomGenerator> rg =
     302                 :     do_GetService("@mozilla.org/security/random-generator;1");
     303                 :   NS_ENSURE_STATE(rg);
     304                 : 
     305                 :   PRUint8* temp;
     306                 :   nsresult rv = rg->GenerateRandomBytes(aSize, &temp);
     307                 :   NS_ENSURE_SUCCESS(rv, rv);
     308                 :   memcpy(_buffer, temp, aSize);
     309                 :   NS_Free(temp);
     310                 :   return NS_OK;
     311                 : #endif
     312                 : }
     313                 : 
     314                 : nsresult
     315            5336 : GenerateGUID(nsCString& _guid)
     316                 : {
     317            5336 :   _guid.Truncate();
     318                 : 
     319                 :   // Request raw random bytes and base64url encode them.  For each set of three
     320                 :   // bytes, we get one character.
     321                 :   const PRUint32 kRequiredBytesLength =
     322            5336 :     static_cast<PRUint32>(GUID_LENGTH / 4 * 3);
     323                 : 
     324                 :   PRUint8 buffer[kRequiredBytesLength];
     325            5336 :   nsresult rv = GenerateRandomBytes(kRequiredBytesLength, buffer);
     326            5336 :   NS_ENSURE_SUCCESS(rv, rv);
     327                 : 
     328            5336 :   rv = Base64urlEncode(buffer, kRequiredBytesLength, _guid);
     329            5336 :   NS_ENSURE_SUCCESS(rv, rv);
     330                 : 
     331            5336 :   NS_ASSERTION(_guid.Length() == GUID_LENGTH, "GUID is not the right size!");
     332            5336 :   return NS_OK;
     333                 : }
     334                 : 
     335                 : bool
     336             471 : IsValidGUID(const nsCString& aGUID)
     337                 : {
     338             471 :   nsCString::size_type len = aGUID.Length();
     339             471 :   if (len != GUID_LENGTH) {
     340             211 :     return false;
     341                 :   }
     342                 : 
     343            6750 :   for (nsCString::size_type i = 0; i < len; i++ ) {
     344            3118 :     char c = aGUID[i];
     345            3118 :     if ((c >= 'a' && c <= 'z') || // a-z
     346                 :         (c >= 'A' && c <= 'Z') || // A-Z
     347                 :         (c >= '0' && c <= '9') || // 0-9
     348                 :         c == '-' || c == '_') { // - or _
     349            3115 :       continue;
     350                 :     }
     351               3 :     return false;
     352                 :   }
     353             257 :   return true;
     354                 : }
     355                 : 
     356                 : void
     357            1782 : TruncateTitle(const nsACString& aTitle, nsACString& aTrimmed)
     358                 : {
     359            1782 :   aTrimmed = aTitle;
     360            1782 :   if (aTitle.Length() > TITLE_LENGTH_MAX) {
     361               4 :     aTrimmed = StringHead(aTitle, TITLE_LENGTH_MAX);
     362                 :   }
     363            1782 : }
     364                 : 
     365                 : void
     366             265 : ForceWALCheckpoint()
     367                 : {
     368             530 :   nsRefPtr<Database> DB = Database::GetDatabase();
     369             265 :   if (DB) {
     370                 :     nsCOMPtr<mozIStorageAsyncStatement> stmt = DB->GetAsyncStatement(
     371                 :       "pragma wal_checkpoint "
     372             530 :     );
     373             265 :     if (stmt) {
     374             530 :       nsCOMPtr<mozIStoragePendingStatement> handle;
     375             265 :       (void)stmt->ExecuteAsync(nsnull, getter_AddRefs(handle));
     376                 :     }
     377                 :   }
     378             265 : }
     379                 : 
     380                 : bool
     381             695 : GetHiddenState(bool aIsRedirect,
     382                 :                PRUint32 aTransitionType)
     383                 : {
     384                 :   return aTransitionType == nsINavHistoryService::TRANSITION_FRAMED_LINK ||
     385                 :          aTransitionType == nsINavHistoryService::TRANSITION_EMBED ||
     386             695 :          aIsRedirect;
     387                 : }
     388                 : 
     389                 : ////////////////////////////////////////////////////////////////////////////////
     390                 : //// PlacesEvent
     391                 : 
     392             266 : PlacesEvent::PlacesEvent(const char* aTopic)
     393             266 : : mTopic(aTopic)
     394                 : {
     395             266 : }
     396                 : 
     397                 : NS_IMETHODIMP
     398             266 : PlacesEvent::Run()
     399                 : {
     400             266 :   Notify();
     401             266 :   return NS_OK;
     402                 : }
     403                 : 
     404                 : void
     405             266 : PlacesEvent::Notify()
     406                 : {
     407             266 :   NS_ASSERTION(NS_IsMainThread(), "Must only be used on the main thread!");
     408             532 :   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
     409             266 :   if (obs) {
     410             266 :     (void)obs->NotifyObservers(nsnull, mTopic, nsnull);
     411                 :   }
     412             266 : }
     413                 : 
     414            1862 : NS_IMPL_THREADSAFE_ISUPPORTS1(
     415                 :   PlacesEvent
     416                 : , nsIRunnable
     417                 : )
     418                 : 
     419                 : ////////////////////////////////////////////////////////////////////////////////
     420                 : //// AsyncStatementCallbackNotifier
     421                 : 
     422                 : NS_IMETHODIMP
     423            4678 : AsyncStatementCallbackNotifier::HandleCompletion(PRUint16 aReason)
     424                 : {
     425            4678 :   if (aReason != mozIStorageStatementCallback::REASON_FINISHED)
     426               0 :     return NS_ERROR_UNEXPECTED;
     427                 : 
     428            9356 :   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     429            4678 :   if (obs) {
     430            4678 :     (void)obs->NotifyObservers(nsnull, mTopic, nsnull);
     431                 :   }
     432                 : 
     433            4678 :   return NS_OK;
     434                 : }
     435                 : 
     436                 : ////////////////////////////////////////////////////////////////////////////////
     437                 : //// AsyncStatementCallbackNotifier
     438                 : 
     439                 : NS_IMETHODIMP
     440              21 : AsyncStatementTelemetryTimer::HandleCompletion(PRUint16 aReason)
     441                 : {
     442              21 :   if (aReason == mozIStorageStatementCallback::REASON_FINISHED) {
     443              21 :     Telemetry::AccumulateTimeDelta(mHistogramId, mStart);
     444                 :   }
     445              21 :   return NS_OK;
     446                 : }
     447                 : 
     448                 : // This is a temporary converter used by nsPlacesImportExportService until
     449                 : // bug 482911 completes its js rewrite.
     450                 : jsval
     451              11 : livemarkInfoToJSVal(PRInt64 aId,
     452                 :                     const nsACString& aGUID,
     453                 :                     const nsAString& aTitle,
     454                 :                     PRInt64 aParentId,
     455                 :                     PRInt32 aIndex,
     456                 :                     nsCOMPtr<nsIURI>& aFeedURI,
     457                 :                     nsCOMPtr<nsIURI>& aSiteURI)
     458                 : {
     459              22 :   nsCOMPtr<nsIXPConnect> xpc = mozilla::services::GetXPConnect();
     460              11 :   NS_ENSURE_TRUE(xpc, JSVAL_NULL);
     461                 : 
     462                 :   nsAXPCNativeCallContext *ncc;
     463              11 :   nsresult rv = xpc->GetCurrentNativeCallContext(&ncc);
     464              11 :   NS_ENSURE_SUCCESS(rv, JSVAL_NULL);
     465              11 :   JSContext *cx = nsnull;
     466              11 :   rv = ncc->GetJSContext(&cx);
     467              11 :   NS_ENSURE_SUCCESS(rv, JSVAL_NULL);
     468              11 :   JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
     469              11 :   NS_ENSURE_TRUE(obj, JSVAL_NULL); 
     470                 : 
     471                 :   jsval id;
     472              11 :   NS_ENSURE_TRUE(JS_NewNumberValue(cx, double(aId), &id), JSVAL_NULL);
     473                 : 
     474              11 :   JSString* guid = JS_NewStringCopyN(cx, PromiseFlatCString(aGUID).get(),
     475              11 :                                      aGUID.Length());
     476              11 :   NS_ENSURE_TRUE(guid, JSVAL_NULL); 
     477                 : 
     478              11 :   JSString* title = JS_NewUCStringCopyN(cx, PromiseFlatString(aTitle).get(),
     479              11 :                                         aTitle.Length());
     480              11 :   NS_ENSURE_TRUE(title, JSVAL_NULL); 
     481                 : 
     482                 :   jsval parentId;
     483              11 :   NS_ENSURE_TRUE(JS_NewNumberValue(cx, double(aParentId), &parentId), JSVAL_NULL);
     484                 : 
     485                 :   jsval feedURI;
     486                 :   rv = nsContentUtils::WrapNative(cx, JS_GetGlobalForScopeChain(cx),
     487              11 :                                   NS_ISUPPORTS_CAST(nsIURI*, aFeedURI), &feedURI);
     488              11 :   NS_ENSURE_SUCCESS(rv, JSVAL_NULL);
     489                 : 
     490                 :   jsval siteURI;
     491                 :   rv = nsContentUtils::WrapNative(cx, JS_GetGlobalForScopeChain(cx),
     492              11 :                                   NS_ISUPPORTS_CAST(nsIURI*, aSiteURI), &siteURI);
     493              11 :   NS_ENSURE_SUCCESS(rv, JSVAL_NULL);
     494                 : 
     495              77 :   if (!JS_DefineProperty(cx, obj, "id", id, NULL, NULL, JSPROP_ENUMERATE) ||
     496              11 :       !JS_DefineProperty(cx, obj, "guid", STRING_TO_JSVAL(guid), NULL, NULL, JSPROP_ENUMERATE) ||
     497              11 :       !JS_DefineProperty(cx, obj, "title", STRING_TO_JSVAL(title), NULL, NULL, JSPROP_ENUMERATE) ||
     498              11 :       !JS_DefineProperty(cx, obj, "parentId", parentId, NULL, NULL, JSPROP_ENUMERATE) ||
     499              11 :       !JS_DefineProperty(cx, obj, "index", INT_TO_JSVAL(aIndex), NULL, NULL, JSPROP_ENUMERATE) ||
     500              11 :       !JS_DefineProperty(cx, obj, "feedURI", feedURI, NULL, NULL, JSPROP_ENUMERATE) ||
     501              11 :       !JS_DefineProperty(cx, obj, "siteURI", siteURI, NULL, NULL, JSPROP_ENUMERATE)) {
     502               0 :     return JSVAL_NULL;
     503                 :   }
     504              11 :   return OBJECT_TO_JSVAL(obj);
     505                 : }
     506                 : 
     507                 : } // namespace places
     508                 : } // namespace mozilla

Generated by: LCOV version 1.7