dom/workers/File.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     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 "File.h"
     9 #include "nsIDOMFile.h"
    10 #include "nsDOMBlobBuilder.h"
    11 #include "nsError.h"
    13 #include "jsapi.h"
    14 #include "jsfriendapi.h"
    15 #include "nsCOMPtr.h"
    16 #include "nsJSUtils.h"
    17 #include "nsString.h"
    19 #include "mozilla/dom/Exceptions.h"
    20 #include "WorkerInlines.h"
    21 #include "WorkerPrivate.h"
    23 USING_WORKERS_NAMESPACE
    24 using mozilla::dom::Throw;
    26 namespace {
    28 class Blob
    29 {
    30   // Blob should never be instantiated.
    31   Blob();
    32   ~Blob();
    34   static const JSClass sClass;
    35   static const JSPropertySpec sProperties[];
    36   static const JSFunctionSpec sFunctions[];
    38 public:
    39   static JSObject*
    40   InitClass(JSContext* aCx, JS::Handle<JSObject*> aObj)
    41   {
    42     return JS_InitClass(aCx, aObj, JS::NullPtr(), &sClass, Construct, 0,
    43                         sProperties, sFunctions, nullptr, nullptr);
    44   }
    46   static JSObject*
    47   Create(JSContext* aCx, nsIDOMBlob* aBlob)
    48   {
    49     MOZ_ASSERT(SameCOMIdentity(static_cast<nsISupports*>(aBlob), aBlob));
    51     JSObject* obj = JS_NewObject(aCx, &sClass, JS::NullPtr(), JS::NullPtr());
    52     if (obj) {
    53       JS_SetPrivate(obj, aBlob);
    54       NS_ADDREF(aBlob);
    55     }
    56     return obj;
    57   }
    59   static nsIDOMBlob*
    60   GetPrivate(JSObject* aObj);
    62 private:
    63   static nsIDOMBlob*
    64   GetInstancePrivate(JSContext* aCx, JS::Handle<JSObject*> aObj, const char* aFunctionName)
    65   {
    66     nsIDOMBlob* blob = GetPrivate(aObj);
    67     if (blob) {
    68       return blob;
    69     }
    71     JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
    72                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
    73                          JS_GetClass(aObj)->name);
    74     return nullptr;
    75   }
    77   static nsIDOMBlob*
    78   Unwrap(JSContext* aCx, JSObject* aObj)
    79   {
    80     return GetPrivate(aObj);
    81   }
    83   static bool
    84   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
    85   {
    86     JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
    88     nsRefPtr<nsDOMMultipartFile> file = new nsDOMMultipartFile();
    89     nsresult rv = file->InitBlob(aCx, args.length(), args.array(), Unwrap);
    90     if (NS_FAILED(rv)) {
    91       return Throw(aCx, rv);
    92     }
    94     JSObject* obj = file::CreateBlob(aCx, file);
    95     if (!obj) {
    96       return false;
    97     }
    99     args.rval().setObject(*obj);
   100     return true;
   101   }
   103   static void
   104   Finalize(JSFreeOp* aFop, JSObject* aObj)
   105   {
   106     MOZ_ASSERT(JS_GetClass(aObj) == &sClass);
   108     nsIDOMBlob* blob = GetPrivate(aObj);
   109     NS_IF_RELEASE(blob);
   110   }
   112   static bool
   113   IsBlob(JS::Handle<JS::Value> v)
   114   {
   115     return v.isObject() && GetPrivate(&v.toObject()) != nullptr;
   116   }
   118   static bool
   119   GetSizeImpl(JSContext* aCx, JS::CallArgs aArgs)
   120   {
   121     JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
   122     nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "size");
   123     MOZ_ASSERT(blob);
   125     uint64_t size;
   126     if (NS_FAILED(blob->GetSize(&size))) {
   127       return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
   128     }
   130     aArgs.rval().setNumber(double(size));
   131     return true;
   132   }
   134   static bool
   135   GetSize(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
   136   {
   137     JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
   138     return JS::CallNonGenericMethod<IsBlob, GetSizeImpl>(aCx, args);
   139   }
   141   static bool
   142   GetTypeImpl(JSContext* aCx, JS::CallArgs aArgs)
   143   {
   144     JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
   145     nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "type");
   146     MOZ_ASSERT(blob);
   148     nsString type;
   149     if (NS_FAILED(blob->GetType(type))) {
   150       return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
   151     }
   153     JSString* jsType = JS_NewUCStringCopyN(aCx, type.get(), type.Length());
   154     if (!jsType) {
   155       return false;
   156     }
   158     aArgs.rval().setString(jsType);
   159     return true;
   160   }
   162   static bool
   163   GetType(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
   164   {
   165     JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
   166     return JS::CallNonGenericMethod<IsBlob, GetTypeImpl>(aCx, args);
   167   }
   169   static bool
   170   Slice(JSContext* aCx, unsigned aArgc, jsval* aVp)
   171   {
   172     JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
   174     JS::Rooted<JSObject*> obj(aCx, args.thisv().toObjectOrNull());
   175     if (!obj) {
   176       return false;
   177     }
   179     nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "slice");
   180     if (!blob) {
   181       return false;
   182     }
   184     double start = 0, end = 0;
   185     JS::Rooted<JSString*> jsContentType(aCx, JS_GetEmptyString(JS_GetRuntime(aCx)));
   186     if (!JS_ConvertArguments(aCx, args, "/IIS", &start,
   187                              &end, jsContentType.address())) {
   188       return false;
   189     }
   191     nsDependentJSString contentType;
   192     if (!contentType.init(aCx, jsContentType)) {
   193       return false;
   194     }
   196     uint8_t optionalArgc = aArgc;
   197     nsCOMPtr<nsIDOMBlob> rtnBlob;
   198     if (NS_FAILED(blob->Slice(static_cast<uint64_t>(start),
   199                               static_cast<uint64_t>(end),
   200                               contentType, optionalArgc,
   201                               getter_AddRefs(rtnBlob)))) {
   202       return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
   203     }
   205     JSObject* rtnObj = file::CreateBlob(aCx, rtnBlob);
   206     if (!rtnObj) {
   207       return false;
   208     }
   210     args.rval().setObject(*rtnObj);
   211     return true;
   212   }
   213 };
   215 const JSClass Blob::sClass = {
   216   "Blob",
   217   JSCLASS_HAS_PRIVATE,
   218   JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   219   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
   220 };
   222 const JSPropertySpec Blob::sProperties[] = {
   223   JS_PSGS("size", GetSize, GetterOnlyJSNative, JSPROP_ENUMERATE),
   224   JS_PSGS("type", GetType, GetterOnlyJSNative, JSPROP_ENUMERATE),
   225   JS_PS_END
   226 };
   228 const JSFunctionSpec Blob::sFunctions[] = {
   229   JS_FN("slice", Slice, 1, JSPROP_ENUMERATE),
   230   JS_FS_END
   231 };
   233 class File : public Blob
   234 {
   235   // File should never be instantiated.
   236   File();
   237   ~File();
   239   static const JSClass sClass;
   240   static const JSPropertySpec sProperties[];
   242 public:
   243   static JSObject*
   244   InitClass(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<JSObject*> aParentProto)
   245   {
   246     return JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct, 0,
   247                         sProperties, nullptr, nullptr, nullptr);
   248   }
   250   static JSObject*
   251   Create(JSContext* aCx, nsIDOMFile* aFile)
   252   {
   253     MOZ_ASSERT(SameCOMIdentity(static_cast<nsISupports*>(aFile), aFile));
   255     JSObject* obj = JS_NewObject(aCx, &sClass, JS::NullPtr(), JS::NullPtr());
   256     if (obj) {
   257       JS_SetPrivate(obj, aFile);
   258       NS_ADDREF(aFile);
   259     }
   260     return obj;
   261   }
   263   static nsIDOMFile*
   264   GetPrivate(JSObject* aObj)
   265   {
   266     if (aObj) {
   267       const JSClass* classPtr = JS_GetClass(aObj);
   268       if (classPtr == &sClass) {
   269         nsISupports* priv = static_cast<nsISupports*>(JS_GetPrivate(aObj));
   270         nsCOMPtr<nsIDOMFile> file = do_QueryInterface(priv);
   271         MOZ_ASSERT_IF(priv, file);
   272         return file;
   273       }
   274     }
   275     return nullptr;
   276   }
   278   static const JSClass*
   279   Class()
   280   {
   281     return &sClass;
   282   }
   284 private:
   285   static nsIDOMFile*
   286   GetInstancePrivate(JSContext* aCx, JS::Handle<JSObject*> aObj, const char* aFunctionName)
   287   {
   288     nsIDOMFile* file = GetPrivate(aObj);
   289     if (file) {
   290       return file;
   291     }
   293     JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
   294                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
   295                          JS_GetClass(aObj)->name);
   296     return nullptr;
   297   }
   299   static bool
   300   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   301   {
   302     JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
   303                          JSMSG_WRONG_CONSTRUCTOR,
   304                          sClass.name);
   305     return false;
   306   }
   308   static void
   309   Finalize(JSFreeOp* aFop, JSObject* aObj)
   310   {
   311     MOZ_ASSERT(JS_GetClass(aObj) == &sClass);
   313     nsIDOMFile* file = GetPrivate(aObj);
   314     NS_IF_RELEASE(file);
   315   }
   317   static bool
   318   IsFile(JS::Handle<JS::Value> v)
   319   {
   320     return v.isObject() && GetPrivate(&v.toObject()) != nullptr;
   321   }
   323   static bool
   324   GetMozFullPathImpl(JSContext* aCx, JS::CallArgs aArgs)
   325   {
   326     JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
   327     nsIDOMFile* file = GetInstancePrivate(aCx, obj, "mozFullPath");
   328     MOZ_ASSERT(file);
   330     nsString fullPath;
   332     if (GetWorkerPrivateFromContext(aCx)->UsesSystemPrincipal() &&
   333         NS_FAILED(file->GetMozFullPathInternal(fullPath))) {
   334       return Throw(aCx, NS_ERROR_DOM_FILE_NOT_READABLE_ERR);
   335     }
   337     JSString* jsFullPath = JS_NewUCStringCopyN(aCx, fullPath.get(),
   338                                                fullPath.Length());
   339     if (!jsFullPath) {
   340       return false;
   341     }
   343     aArgs.rval().setString(jsFullPath);
   344     return true;
   345   }
   347   static bool
   348   GetMozFullPath(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
   349   {
   350     JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
   351     return JS::CallNonGenericMethod<IsFile, GetMozFullPathImpl>(aCx, args);
   352   }
   354   static bool
   355   GetNameImpl(JSContext* aCx, JS::CallArgs aArgs)
   356   {
   357     JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
   358     nsIDOMFile* file = GetInstancePrivate(aCx, obj, "name");
   359     MOZ_ASSERT(file);
   361     nsString name;
   362     if (NS_FAILED(file->GetName(name))) {
   363       name.Truncate();
   364     }
   366     JSString* jsName = JS_NewUCStringCopyN(aCx, name.get(), name.Length());
   367     if (!jsName) {
   368       return false;
   369     }
   371     aArgs.rval().setString(jsName);
   372     return true;
   373   }
   375   static bool
   376   GetName(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
   377   {
   378     JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
   379     return JS::CallNonGenericMethod<IsFile, GetNameImpl>(aCx, args);
   380   }
   382   static bool
   383   GetPathImpl(JSContext* aCx, JS::CallArgs aArgs)
   384   {
   385     JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
   386     nsIDOMFile* file = GetInstancePrivate(aCx, obj, "path");
   387     MOZ_ASSERT(file);
   389     nsString path;
   390     if (NS_FAILED(file->GetPath(path))) {
   391       path.Truncate();
   392     }
   394     JSString* jsPath = JS_NewUCStringCopyN(aCx, path.get(), path.Length());
   395     if (!jsPath) {
   396       return false;
   397     }
   399     aArgs.rval().setString(jsPath);
   400     return true;
   401   }
   403   static bool
   404   GetPath(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
   405   {
   406     JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
   407     return JS::CallNonGenericMethod<IsFile, GetPathImpl>(aCx, args);
   408   }
   410   static bool
   411   GetLastModifiedDateImpl(JSContext* aCx, JS::CallArgs aArgs)
   412   {
   413     JS::Rooted<JSObject*> obj(aCx, &aArgs.thisv().toObject());
   414     nsIDOMFile* file = GetInstancePrivate(aCx, obj, "lastModifiedDate");
   415     MOZ_ASSERT(file);
   417     if (NS_FAILED(file->GetLastModifiedDate(aCx, aArgs.rval()))) {
   418       return false;
   419     }
   420     return true;
   421   }
   423   static bool
   424   GetLastModifiedDate(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
   425   {
   426     JS::CallArgs args = JS::CallArgsFromVp(aArgc, aVp);
   427     return JS::CallNonGenericMethod<IsFile, GetLastModifiedDateImpl>(aCx, args);
   428   }
   429 };
   431 const JSClass File::sClass = {
   432   "File",
   433   JSCLASS_HAS_PRIVATE,
   434   JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
   435   JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
   436 };
   438 const JSPropertySpec File::sProperties[] = {
   439   JS_PSGS("name", GetName, GetterOnlyJSNative, JSPROP_ENUMERATE),
   440   JS_PSGS("path", GetPath, GetterOnlyJSNative, JSPROP_ENUMERATE),
   441   JS_PSGS("lastModifiedDate", GetLastModifiedDate, GetterOnlyJSNative,
   442           JSPROP_ENUMERATE),
   443   JS_PSGS("mozFullPath", GetMozFullPath, GetterOnlyJSNative, JSPROP_ENUMERATE),
   444   JS_PS_END
   445 };
   447 nsIDOMBlob*
   448 Blob::GetPrivate(JSObject* aObj)
   449 {
   450   if (aObj) {
   451     const JSClass* classPtr = JS_GetClass(aObj);
   452     if (classPtr == &sClass || classPtr == File::Class()) {
   453       nsISupports* priv = static_cast<nsISupports*>(JS_GetPrivate(aObj));
   454       nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(priv);
   455       MOZ_ASSERT_IF(priv, blob);
   456       return blob;
   457     }
   458   }
   459   return nullptr;
   460 }
   462 } // anonymous namespace
   464 BEGIN_WORKERS_NAMESPACE
   466 namespace file {
   468 JSObject*
   469 CreateBlob(JSContext* aCx, nsIDOMBlob* aBlob)
   470 {
   471   return Blob::Create(aCx, aBlob);
   472 }
   474 bool
   475 InitClasses(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
   476 {
   477   JS::Rooted<JSObject*> blobProto(aCx, Blob::InitClass(aCx, aGlobal));
   478   return blobProto && File::InitClass(aCx, aGlobal, blobProto);
   479 }
   481 nsIDOMBlob*
   482 GetDOMBlobFromJSObject(JSObject* aObj)
   483 {
   484   return Blob::GetPrivate(aObj);
   485 }
   487 JSObject*
   488 CreateFile(JSContext* aCx, nsIDOMFile* aFile)
   489 {
   490   return File::Create(aCx, aFile);
   491 }
   493 nsIDOMFile*
   494 GetDOMFileFromJSObject(JSObject* aObj)
   495 {
   496   return File::GetPrivate(aObj);
   497 }
   499 } // namespace file
   501 END_WORKERS_NAMESPACE

mercurial