media/gmp-clearkey/0.1/ClearKeyStorage.cpp
author Gregory Szorc <gps@mozilla.com>
Tue, 24 Feb 2015 15:16:54 -0800
changeset 245746 6d143a910f5ecf67d9dec302087aa20777ec6772
parent 242266 533acf8bbd7f5b5f7aa609e5cc5a8290e6d3c372
child 252249 ac4464790ec4896a5188fa50cfc69ae0ffeddc08
permissions -rw-r--r--
Bug 1132771 - Add Files to moz.build with ability to define Bugzilla component The Files sub-context allows us to attach metadata to files based on pattern matching rules. Patterns are matched against files in a last-write-wins fashion. The sub-context defines the BUG_COMPONENT variable, which is a 2-tuple (actually a named tuple) defining the Bugzilla product and component for files. There are no consumers yet. But an eventual use case will be to suggest a bug component for a patch/commit. Another will be to automatically suggest a bug component for a failing test.

/* 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 "ClearKeyStorage.h"
#include "ClearKeyUtils.h"

#include "gmp-task-utils.h"

#include "mozilla/Assertions.h"
#include "mozilla/ArrayUtils.h"

#include <vector>

static GMPErr
RunOnMainThread(GMPTask* aTask)
{
  return GetPlatform()->runonmainthread(aTask);
}

GMPErr
OpenRecord(const char* aName,
           uint32_t aNameLength,
           GMPRecord** aOutRecord,
           GMPRecordClient* aClient)
{
  return GetPlatform()->createrecord(aName, aNameLength, aOutRecord, aClient);
}

class WriteRecordClient : public GMPRecordClient {
public:
  /*
   * This function will take the memory ownership of the parameters and
   * delete them when done.
   */
  static void Write(const std::string& aRecordName,
                    const std::vector<uint8_t>& aData,
                    GMPTask* aOnSuccess,
                    GMPTask* aOnFailure) {
    (new WriteRecordClient(aData, aOnSuccess, aOnFailure))->Do(aRecordName);
  }

  virtual void OpenComplete(GMPErr aStatus) MOZ_OVERRIDE {
    if (GMP_FAILED(aStatus) ||
        GMP_FAILED(mRecord->Write(&mData.front(), mData.size()))) {
      Done(mOnFailure, mOnSuccess);
    }
  }

  virtual void ReadComplete(GMPErr aStatus,
                            const uint8_t* aData,
                            uint32_t aDataSize) MOZ_OVERRIDE {
    MOZ_ASSERT(false, "Should not reach here.");
  }

  virtual void WriteComplete(GMPErr aStatus) MOZ_OVERRIDE {
    if (GMP_FAILED(aStatus)) {
      Done(mOnFailure, mOnSuccess);
    } else {
      Done(mOnSuccess, mOnFailure);
    }
  }

private:
  WriteRecordClient(const std::vector<uint8_t>& aData,
                    GMPTask* aOnSuccess,
                    GMPTask* aOnFailure)
    : mRecord(nullptr)
    , mOnSuccess(aOnSuccess)
    , mOnFailure(aOnFailure)
    , mData(aData) {}

  void Do(const std::string& aName) {
    auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this);
    if (GMP_FAILED(err) ||
        GMP_FAILED(mRecord->Open())) {
      Done(mOnFailure, mOnSuccess);
    }
  }

  void Done(GMPTask* aToRun, GMPTask* aToDestroy) {
    // Note: Call Close() before running continuation, in case the
    // continuation tries to open the same record; if we call Close()
    // after running the continuation, the Close() call will arrive
    // just after the Open() call succeeds, immediately closing the
    // record we just opened.
    if (mRecord) {
      mRecord->Close();
    }
    aToDestroy->Destroy();
    RunOnMainThread(aToRun);
    delete this;
  }

  GMPRecord* mRecord;
  GMPTask* mOnSuccess;
  GMPTask* mOnFailure;
  const std::vector<uint8_t> mData;
};

void
StoreData(const std::string& aRecordName,
          const std::vector<uint8_t>& aData,
          GMPTask* aOnSuccess,
          GMPTask* aOnFailure)
{
  WriteRecordClient::Write(aRecordName, aData, aOnSuccess, aOnFailure);
}

class ReadRecordClient : public GMPRecordClient {
public:
  /*
   * This function will take the memory ownership of the parameters and
   * delete them when done.
   */
  static void Read(const std::string& aRecordName,
                   ReadContinuation* aContinuation) {
    MOZ_ASSERT(aContinuation);
    (new ReadRecordClient(aContinuation))->Do(aRecordName);
  }

  virtual void OpenComplete(GMPErr aStatus) MOZ_OVERRIDE {
    auto err = aStatus;
    if (GMP_FAILED(err) ||
        GMP_FAILED(err = mRecord->Read())) {
      Done(err, nullptr, 0);
    }
  }

  virtual void ReadComplete(GMPErr aStatus,
                            const uint8_t* aData,
                            uint32_t aDataSize) MOZ_OVERRIDE {
    Done(aStatus, aData, aDataSize);
  }

  virtual void WriteComplete(GMPErr aStatus) MOZ_OVERRIDE {
    MOZ_ASSERT(false, "Should not reach here.");
  }

private:
  explicit ReadRecordClient(ReadContinuation* aContinuation)
    : mRecord(nullptr)
    , mContinuation(aContinuation) {}

  void Do(const std::string& aName) {
    auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this);
    if (GMP_FAILED(err) ||
        GMP_FAILED(err = mRecord->Open())) {
      Done(err, nullptr, 0);
    }
  }

  void Done(GMPErr err, const uint8_t* aData, uint32_t aDataSize) {
    // Note: Call Close() before running continuation, in case the
    // continuation tries to open the same record; if we call Close()
    // after running the continuation, the Close() call will arrive
    // just after the Open() call succeeds, immediately closing the
    // record we just opened.
    if (mRecord) {
      mRecord->Close();
    }
    mContinuation->ReadComplete(err, aData, aDataSize);
    delete mContinuation;
    delete this;
  }

  GMPRecord* mRecord;
  ReadContinuation* mContinuation;
};

void
ReadData(const std::string& aRecordName,
         ReadContinuation* aContinuation)
{
  ReadRecordClient::Read(aRecordName, aContinuation);
}

GMPErr
EnumRecordNames(RecvGMPRecordIteratorPtr aRecvIteratorFunc)
{
  return GetPlatform()->getrecordenumerator(aRecvIteratorFunc, nullptr);
}