forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			229 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "FileCreatorHelper.h"
 | |
| 
 | |
| #include "mozilla/dom/BindingDeclarations.h"
 | |
| #include "mozilla/dom/ContentChild.h"
 | |
| #include "mozilla/dom/ContentParent.h"
 | |
| #include "mozilla/dom/FileBinding.h"
 | |
| #include "mozilla/dom/File.h"
 | |
| #include "mozilla/dom/Promise.h"
 | |
| #include "nsContentUtils.h"
 | |
| #include "nsPIDOMWindow.h"
 | |
| #include "nsIFile.h"
 | |
| 
 | |
| // Undefine the macro of CreateFile to avoid FileCreatorHelper#CreateFile being
 | |
| // replaced by FileCreatorHelper#CreateFileW.
 | |
| #ifdef CreateFile
 | |
| #undef CreateFile
 | |
| #endif
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace dom {
 | |
| 
 | |
| /* static */ already_AddRefed<Promise>
 | |
| FileCreatorHelper::CreateFile(nsIGlobalObject* aGlobalObject,
 | |
|                               nsIFile* aFile,
 | |
|                               const ChromeFilePropertyBag& aBag,
 | |
|                               bool aIsFromNsIFile,
 | |
|                               ErrorResult& aRv)
 | |
| {
 | |
|   MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread());
 | |
| 
 | |
|   RefPtr<Promise> promise = Promise::Create(aGlobalObject, aRv);
 | |
|   if (NS_WARN_IF(aRv.Failed())) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobalObject);
 | |
| 
 | |
|   // Parent process
 | |
| 
 | |
|   if (XRE_IsParentProcess()) {
 | |
|     RefPtr<File> file =
 | |
|       CreateFileInternal(window, aFile, aBag, aIsFromNsIFile, aRv);
 | |
|     if (aRv.Failed()) {
 | |
|       return nullptr;
 | |
|     }
 | |
|     promise->MaybeResolve(file);
 | |
|     return promise.forget();
 | |
|   }
 | |
| 
 | |
|   // Content process.
 | |
| 
 | |
|   ContentChild* cc = ContentChild::GetSingleton();
 | |
|   if (!cc) {
 | |
|     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
 | |
|     return promise.forget();
 | |
|   }
 | |
| 
 | |
|   if (!cc->GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE) &&
 | |
|       !Preferences::GetBool("dom.file.createInChild", false)) {
 | |
|     // If this pref is not set and the request is received by the parent
 | |
|     // process, this child is killed for security reason.
 | |
|     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
 | |
|     return promise.forget();
 | |
|   }
 | |
| 
 | |
|   RefPtr<FileCreatorHelper> helper = new FileCreatorHelper(promise, window);
 | |
| 
 | |
|   // The request is sent to the parent process and it's kept alive by
 | |
|   // ContentChild.
 | |
|   helper->SendRequest(aFile, aBag, aIsFromNsIFile, aRv);
 | |
|   if (NS_WARN_IF(aRv.Failed())) {
 | |
|     return nullptr;
 | |
|   }
 | |
| 
 | |
|   return promise.forget();
 | |
| }
 | |
| 
 | |
| /* static */ already_AddRefed<File>
 | |
| FileCreatorHelper::CreateFileInternal(nsPIDOMWindowInner* aWindow,
 | |
|                                       nsIFile* aFile,
 | |
|                                       const ChromeFilePropertyBag& aBag,
 | |
|                                       bool aIsFromNsIFile,
 | |
|                                       ErrorResult& aRv)
 | |
| {
 | |
|   bool lastModifiedPassed = false;
 | |
|   int64_t lastModified = 0;
 | |
|   if (aBag.mLastModified.WasPassed()) {
 | |
|     lastModifiedPassed = true;
 | |
|     lastModified = aBag.mLastModified.Value();
 | |
|   }
 | |
| 
 | |
|   RefPtr<BlobImpl> blobImpl;
 | |
|   aRv = CreateBlobImpl(aFile, aBag.mType, aBag.mName, lastModifiedPassed,
 | |
|                        lastModified, aBag.mExistenceCheck, aIsFromNsIFile,
 | |
|                        getter_AddRefs(blobImpl));
 | |
|   if (aRv.Failed()) {
 | |
|      return nullptr;
 | |
|   }
 | |
| 
 | |
|   RefPtr<File> file = File::Create(aWindow, blobImpl);
 | |
|   return file.forget();
 | |
| }
 | |
| 
 | |
| FileCreatorHelper::FileCreatorHelper(Promise* aPromise,
 | |
|                                      nsPIDOMWindowInner* aWindow)
 | |
|   : mPromise(aPromise)
 | |
|   , mWindow(aWindow)
 | |
| {
 | |
|   MOZ_ASSERT(aPromise);
 | |
| }
 | |
| 
 | |
| FileCreatorHelper::~FileCreatorHelper()
 | |
| {
 | |
| }
 | |
| 
 | |
| void
 | |
| FileCreatorHelper::SendRequest(nsIFile* aFile,
 | |
|                                const ChromeFilePropertyBag& aBag,
 | |
|                                bool aIsFromNsIFile,
 | |
|                                ErrorResult& aRv)
 | |
| {
 | |
|   MOZ_ASSERT(aFile);
 | |
| 
 | |
|   ContentChild* cc = ContentChild::GetSingleton();
 | |
|   if (NS_WARN_IF(!cc)) {
 | |
|     aRv.Throw(NS_ERROR_FAILURE);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   nsID uuid;
 | |
|   aRv = nsContentUtils::GenerateUUIDInPlace(uuid);
 | |
|   if (NS_WARN_IF(aRv.Failed())) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   nsAutoString path;
 | |
|   aRv = aFile->GetPath(path);
 | |
|   if (NS_WARN_IF(aRv.Failed())) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   cc->FileCreationRequest(uuid, this, path, aBag.mType, aBag.mName,
 | |
|                           aBag.mLastModified, aBag.mExistenceCheck,
 | |
|                           aIsFromNsIFile);
 | |
| }
 | |
| 
 | |
| void
 | |
| FileCreatorHelper::ResponseReceived(BlobImpl* aBlobImpl, nsresult aRv)
 | |
| {
 | |
|   if (NS_FAILED(aRv)) {
 | |
|     mPromise->MaybeReject(aRv);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   RefPtr<File> file = File::Create(mWindow, aBlobImpl);
 | |
|   mPromise->MaybeResolve(file);
 | |
| }
 | |
| 
 | |
| /* static */ nsresult
 | |
| FileCreatorHelper::CreateBlobImplForIPC(const nsAString& aPath,
 | |
|                                         const nsAString& aType,
 | |
|                                         const nsAString& aName,
 | |
|                                         bool aLastModifiedPassed,
 | |
|                                         int64_t aLastModified,
 | |
|                                         bool aExistenceCheck,
 | |
|                                         bool aIsFromNsIFile,
 | |
|                                         BlobImpl** aBlobImpl)
 | |
| {
 | |
|   nsCOMPtr<nsIFile> file;
 | |
|   nsresult rv = NS_NewLocalFile(aPath, true, getter_AddRefs(file));
 | |
|   if (NS_WARN_IF(NS_FAILED(rv))) {
 | |
|     return rv;
 | |
|   }
 | |
| 
 | |
|   return CreateBlobImpl(file, aType, aName, aLastModifiedPassed, aLastModified,
 | |
|                         aExistenceCheck, aIsFromNsIFile, aBlobImpl);
 | |
| }
 | |
| 
 | |
| /* static */ nsresult
 | |
| FileCreatorHelper::CreateBlobImpl(nsIFile* aFile,
 | |
|                                   const nsAString& aType,
 | |
|                                   const nsAString& aName,
 | |
|                                   bool aLastModifiedPassed,
 | |
|                                   int64_t aLastModified,
 | |
|                                   bool aExistenceCheck,
 | |
|                                   bool aIsFromNsIFile,
 | |
|                                   BlobImpl** aBlobImpl)
 | |
| {
 | |
|   if (!aExistenceCheck) {
 | |
|     RefPtr<FileBlobImpl> impl = new FileBlobImpl(aFile);
 | |
| 
 | |
|     if (!aName.IsEmpty()) {
 | |
|       impl->SetName(aName);
 | |
|     }
 | |
| 
 | |
|     if (!aType.IsEmpty()) {
 | |
|       impl->SetType(aType);
 | |
|     }
 | |
| 
 | |
|     if (aLastModifiedPassed) {
 | |
|       impl->SetLastModified(aLastModified);
 | |
|     }
 | |
| 
 | |
|     impl.forget(aBlobImpl);
 | |
|     return NS_OK;
 | |
|   }
 | |
| 
 | |
|   RefPtr<MultipartBlobImpl> impl = new MultipartBlobImpl(EmptyString());
 | |
|   nsresult rv =
 | |
|     impl->InitializeChromeFile(aFile, aType, aName, aLastModifiedPassed,
 | |
|                                aLastModified, aIsFromNsIFile);
 | |
|   if (NS_FAILED(rv)) {
 | |
|     return rv;
 | |
|   }
 | |
| 
 | |
|   MOZ_ASSERT(impl->IsFile());
 | |
| 
 | |
|   impl.forget(aBlobImpl);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| } // dom namespace
 | |
| } // mozilla namespace
 | 
