Skip to content

Latest commit

 

History

History
261 lines (214 loc) · 7.23 KB

Call_To_nsIQuotaManagerService_API.md

File metadata and controls

261 lines (214 loc) · 7.23 KB

Call an nsIQuotaManagerService API

  • JS requets to clear quota usage under one origin through nsIQuotaManagerService::clearStoragesForPrincipal api

  • QuotaManagerService::ClearStoragesForPrincipal (api implementation) would receive the call.

    • Prepare the Clear Origin request

        // Prepare the Clear Origin request 
        RefPtr<Request> request = new Request(aPrincipal);
        ClearOriginParams params;
    • Initiate the request

        nsAutoPtr<PendingRequestInfo> info(new RequestInfo(request, params));
        rv = InitiateRequest(info);
  • QuotaManagerService::RequestInfo::InitiateRequest

    • Create the requet actor

        auto actor = new QuotaRequestChild(request);
    • Send out the requet actor to Parent through IPC

        // This is done by `PQuotaChild::SendPQuotaRequestConstructor`
        aActor->SendPQuotaRequestConstructor(actor, mParams)
  • Quota::RecvPQuotaUsageRequestConstructor

    • Parent receives the request and runs it
        auto* op = static_cast<QuotaUsageRequestBase*>(aActor);
        // ... ...
        op->RunImmediately();
  • NormalOriginOperationBase::RunImmediately

  • OriginOperationBase::Run

    OriginOperationBase would do task according the current state as well as advance the state after doing task. For exmaple, as we started at the State_Initializing.

    • OriginOperationBase::Run

        case State_Initializing: {
          rv = InitOnMainThread();
          break;
        }
    • OriginOperationBase::InitOnMainThread

      • nsresult rv = DoInitOnMainThread();

        • ClearOriginOp::DoInitOnMainThread
            // This step is important.
            // Our aClearAll flag takes effect here.
            if (mParams.clearAll()) {
              mOriginScope.SetFromPrefix(origin);
            } else {
              mOriginScope.SetFromOrigin(origin);
            }
      • After init on the main thread, advance the state from "State_Initializing" to "State_FinishingInit"

          AdvanceState();
          // Dispatch to the main thread to do `::Run` again
          MOZ_ALWAYS_SUCCEEDS(mOwningThread->Dispatch(this, NS_DISPATCH_NORMAL));
      • After a series of jobs and the states changes, we would arrive the "State_DirectoryOpenPending" state

    • OriginOperationBase::Run

        case State_DirectoryOpenPending: {
          rv = DirectoryOpen();
          break;
        }
  • OriginOperationBase::DirectoryOpen

    • Advance to the next state

       AdvanceState();
    • OriginOperationBase::AdvanceState

      • Advance State_DirectoryOpenPending to State_DirectoryWorkOpen
           case State_DirectoryOpenPending:
             mState = State_DirectoryWorkOpen;
             return;
    • Dispatch to the IO thread to handle the new state

      nsresult rv = quotaManager->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL);
  • OriginOperationBase::Run

        case State_DirectoryWorkOpen: {
          // The same, inside `DirectoryWork` after jobs are done,
          // the state would be advanced and dispatch to the IO thread to run the new state again.
          rv = DirectoryWork();
          break;
        }
  • OriginOperationBase::DirectoryWork

    After advancing state, it would arrive this metod.

    • Ensure storage initialized then do directory work
        if (mNeedsQuotaManagerInit) {
          rv = quotaManager->EnsureStorageIsInitialized();
          if (NS_WARN_IF(NS_FAILED(rv))) {
            return rv;
          }
        }
      
        // ... ...
        
        rv = DoDirectoryWork(quotaManager);
  • ClearRequestBase::DoDirectoryWork (How did it know ClearRequestBase)

  • ClearRequestBase::DeleteFiles

    • Init the path to the storage dir for a particular persistent type

        rv = directory->InitWithPath(aQuotaManager->GetStoragePath(aPersistenceType));
    • Get entries under the storage dir

        nsCOMPtr<nsISimpleEnumerator> entries;
        if (NS_WARN_IF(NS_FAILED(
              directory->GetDirectoryEntries(getter_AddRefs(entries)))) || !entries) {
          return;
        }
    • Find the matched origin then remove its storage directory

        nsString leafName;
        rv = file->GetLeafName(leafName);
        
        // ... ...
        
        
        if (!isDirectory) {
          // Unknown files during clearing are allowed. Just warn if we find them.
          if (!IsOSMetadata(leafName)) {
            UNKNOWN_FILE_WARNING(leafName);
          }
          continue;
        }
        
        // Skip the origin directory if it doesn't match the pattern.
        if (!originScope.MatchesOrigin(OriginScope::FromOrigin(
                                         NS_ConvertUTF16toUTF8(leafName)))) {
          continue;
        }
      • OriginScope::MatchesOrigin
        • Because of the aClearAll flag, OA dosen't matter here. We would continue to clear across OAs
            // ... ...
            else if (IsPrefix()) {
              MOZ_ASSERT(mPrefix);
              match = StringBeginsWith(aOther.mOriginAndAttributes->mOrigin, *mPrefix);
            }
            // ... ...
        // ... ...
        
         for (uint32_t index = 0; index < 10; index++) {
           // We can't guarantee that this will always succeed on Windows...
           if (NS_SUCCEEDED((rv = file->Remove(true)))) {
             break;
           }
           // ... ...
         }
         
         // ... ...
         
         aQuotaManager->OriginClearCompleted(aPersistenceType, origin);
  • OriginOperationBase::DirectoryWork

    Back to DirectoryWork then the state is advacned from "State_DirectoryWorkOpen" to "State_UnblockingOpen"

  • OriginOperationBase::Run

    • Unblock lock
          case State_UnblockingOpen: {
            UnblockOpen();
            return NS_OK;
          }
  • NormalOriginOperationBase::UnblockOpen

    • Send results

        SendResults();
    • After sending results, release the lock then advance the state from "State_UnblockingOpen" to "State_Complete"

        mDirectoryLock = nullptr;
        AdvanceState();
  • QuotaRequestBase::SendResults (continues from the above SendResults)

    • Send result back to Child through IPC
        Unused << PQuotaRequestParent::Send__delete__(this, response);
  • QuotaRequestChild::Recv__delete__

    • Handle response from clearing job
          case RequestResponse::TInitResponse:
          case RequestResponse::TClearOriginResponse:
          case RequestResponse::TClearDataResponse:
          case RequestResponse::TClearAllResponse:
          case RequestResponse::TResetAllResponse:
          case RequestResponse::TPersistResponse:
            HandleResponse();
            break;
  • QuotaRequestChild::HandleResponse

      mRequest->SetResult(variant)
  • Request::SetResult

      FireCallback();
  • Request::FireCallback

    • Fire nsIQuotaRequest::nsIQuotaCallback::onComplete to send result back to JS side
        if (mCallback) {
          mCallback->OnComplete(this);
          // Clean up.
          mCallback = nullptr;
        }