storage/src/mozStorageStatementRow.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "nsMemory.h"
     8 #include "nsString.h"
    10 #include "mozStorageStatementRow.h"
    11 #include "mozStorageStatement.h"
    13 #include "jsapi.h"
    15 namespace mozilla {
    16 namespace storage {
    18 ////////////////////////////////////////////////////////////////////////////////
    19 //// StatementRow
    21 StatementRow::StatementRow(Statement *aStatement)
    22 : mStatement(aStatement)
    23 {
    24 }
    26 NS_IMPL_ISUPPORTS(
    27   StatementRow,
    28   mozIStorageStatementRow,
    29   nsIXPCScriptable
    30 )
    32 ////////////////////////////////////////////////////////////////////////////////
    33 //// nsIXPCScriptable
    35 #define XPC_MAP_CLASSNAME StatementRow
    36 #define XPC_MAP_QUOTED_CLASSNAME "StatementRow"
    37 #define XPC_MAP_WANT_GETPROPERTY
    38 #define XPC_MAP_WANT_NEWRESOLVE
    39 #define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
    40 #include "xpc_map_end.h"
    42 NS_IMETHODIMP
    43 StatementRow::GetProperty(nsIXPConnectWrappedNative *aWrapper,
    44                           JSContext *aCtx,
    45                           JSObject *aScopeObj,
    46                           jsid aId,
    47                           jsval *_vp,
    48                           bool *_retval)
    49 {
    50   NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
    52   JS::RootedObject scope(aCtx, aScopeObj);
    53   if (JSID_IS_STRING(aId)) {
    54     ::JSAutoByteString idBytes(aCtx, JSID_TO_STRING(aId));
    55     NS_ENSURE_TRUE(!!idBytes, NS_ERROR_OUT_OF_MEMORY);
    56     nsDependentCString jsid(idBytes.ptr());
    58     uint32_t idx;
    59     nsresult rv = mStatement->GetColumnIndex(jsid, &idx);
    60     NS_ENSURE_SUCCESS(rv, rv);
    61     int32_t type;
    62     rv = mStatement->GetTypeOfIndex(idx, &type);
    63     NS_ENSURE_SUCCESS(rv, rv);
    65     if (type == mozIStorageValueArray::VALUE_TYPE_INTEGER ||
    66         type == mozIStorageValueArray::VALUE_TYPE_FLOAT) {
    67       double dval;
    68       rv = mStatement->GetDouble(idx, &dval);
    69       NS_ENSURE_SUCCESS(rv, rv);
    70       *_vp = ::JS_NumberValue(dval);
    71     }
    72     else if (type == mozIStorageValueArray::VALUE_TYPE_TEXT) {
    73       uint32_t bytes;
    74       const jschar *sval = reinterpret_cast<const jschar *>(
    75         static_cast<mozIStorageStatement *>(mStatement)->
    76           AsSharedWString(idx, &bytes)
    77       );
    78       JSString *str = ::JS_NewUCStringCopyN(aCtx, sval, bytes / 2);
    79       if (!str) {
    80         *_retval = false;
    81         return NS_OK;
    82       }
    83       *_vp = STRING_TO_JSVAL(str);
    84     }
    85     else if (type == mozIStorageValueArray::VALUE_TYPE_BLOB) {
    86       uint32_t length;
    87       const uint8_t *blob = static_cast<mozIStorageStatement *>(mStatement)->
    88         AsSharedBlob(idx, &length);
    89       JSObject *obj = ::JS_NewArrayObject(aCtx, length);
    90       if (!obj) {
    91         *_retval = false;
    92         return NS_OK;
    93       }
    94       *_vp = OBJECT_TO_JSVAL(obj);
    96       // Copy the blob over to the JS array.
    97       for (uint32_t i = 0; i < length; i++) {
    98         if (!::JS_SetElement(aCtx, scope, i, blob[i])) {
    99           *_retval = false;
   100           return NS_OK;
   101         }
   102       }
   103     }
   104     else if (type == mozIStorageValueArray::VALUE_TYPE_NULL) {
   105       *_vp = JSVAL_NULL;
   106     }
   107     else {
   108       NS_ERROR("unknown column type returned, what's going on?");
   109     }
   110   }
   112   return NS_OK;
   113 }
   115 NS_IMETHODIMP
   116 StatementRow::NewResolve(nsIXPConnectWrappedNative *aWrapper,
   117                          JSContext *aCtx,
   118                          JSObject *aScopeObj,
   119                          jsid aId,
   120                          JSObject **_objp,
   121                          bool *_retval)
   122 {
   123   JS::Rooted<JSObject*> scopeObj(aCtx, aScopeObj);
   125   NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
   126   // We do not throw at any point after this because we want to allow the
   127   // prototype chain to be checked for the property.
   129   if (JSID_IS_STRING(aId)) {
   130     ::JSAutoByteString idBytes(aCtx, JSID_TO_STRING(aId));
   131     NS_ENSURE_TRUE(!!idBytes, NS_ERROR_OUT_OF_MEMORY);
   132     nsDependentCString name(idBytes.ptr());
   134     uint32_t idx;
   135     nsresult rv = mStatement->GetColumnIndex(name, &idx);
   136     if (NS_FAILED(rv)) {
   137       // It's highly likely that the name doesn't exist, so let the JS engine
   138       // check the prototype chain and throw if that doesn't have the property
   139       // either.
   140       *_objp = nullptr;
   141       return NS_OK;
   142     }
   144     *_retval = ::JS_DefinePropertyById(aCtx, scopeObj, aId, JSVAL_VOID,
   145                                      nullptr, nullptr, 0);
   146     *_objp = scopeObj;
   147     return NS_OK;
   148   }
   150   return NS_OK;
   151 }
   153 } // namespace storage
   154 } // namescape mozilla

mercurial