<commit_before>
{%partial doc .%}
NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
  {%partial guardArguments .%}
  if (info.Length() == {{args|jsArgsCount}} || !info[{{args|jsArgsCount}}]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  {{ cppFunctionName }}Baton* baton = new {{ cppFunctionName }}Baton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

  {%each args|argsInfo as arg %}
    {%if arg.globalPayload %}
      {{ cppFunctionName }}_globalPayload* globalPayload = new {{ cppFunctionName }}_globalPayload;
    {%endif%}
  {%endeach%}

  {%each args|argsInfo as arg %}
    {%if not arg.isReturn %}
      {%if arg.isSelf %}
        baton->{{ arg.name }} = Nan::ObjectWrap::Unwrap<{{ arg.cppClassName }}>(info.This())->GetValue();
      {%elsif arg.isCallbackFunction %}
        if (!info[{{ arg.jsArg }}]->IsFunction()) {
          baton->{{ arg.name }} = NULL;
        {%if arg.payload.globalPayload %}
          globalPayload->{{ arg.name }} = NULL;
        {%else%}
          // NOTE this is a dead path
          baton->{{ arg.payload.name }} = NULL;
        {%endif%}
        }
        else {
          baton->{{ arg.name}} = {{ cppFunctionName }}_{{ arg.name }}_cppCallback;
          {%if arg.payload.globalPayload %}
            globalPayload->{{ arg.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As<Function>());
          {%else%}
            // NOTE this is a dead path
            baton->{{ arg.payload.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As<Function>());
          {%endif%}
        }
      {%elsif arg.payloadFor %}
        {%if arg.globalPayload %}
          baton->{{ arg.name }} = globalPayload;
        {%endif%}
      {%elsif arg.name %}
        {%partial convertFromV8 arg%}
        {%if not arg.payloadFor %}
          baton->{{ arg.name }} = from_{{ arg.name }};
          {%if arg | isOid %}
            baton->{{ arg.name }}NeedsFree = info[{{ arg.jsArg }}]->IsString();
          {%endif%}
        {%endif%}
      {%endif%}
    {%elsif arg.shouldAlloc %}
      baton->{{arg.name}} = ({{ arg.cType }})malloc(sizeof({{ arg.cType|replace '*' '' }}));
      {%if arg.cppClassName == "GitBuf" %}
        baton->{{arg.name}}->ptr = NULL;
        baton->{{arg.name}}->size = baton->{{arg.name}}->asize = 0;
      {%endif%}
    {%endif%}
  {%endeach%}

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[{{args|jsArgsCount}}]));
  {{ cppFunctionName }}Worker *worker = new {{ cppFunctionName }}Worker(baton, callback);

  {%each args|argsInfo as arg %}
    {%if not arg.isReturn %}
      {%if arg.isSelf %}
        worker->SaveToPersistent("{{ arg.name }}", info.This());
      {%elsif not arg.isCallbackFunction %}
        if (!info[{{ arg.jsArg }}]->IsUndefined() && !info[{{ arg.jsArg }}]->IsNull())
          worker->SaveToPersistent("{{ arg.name }}", Nan::To<v8::Object>(info[{{ arg.jsArg }}]).ToLocalChecked());
      {%endif%}
    {%endif%}
  {%endeach%}

  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster {{ cppClassName }}::{{ cppFunctionName }}Worker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
    {%each args|argsInfo as arg %}
      {%if arg.cType|isPointer%}
        {%if not arg.cType|isDoublePointer%}
          ,baton->{{ arg.name }}
        {%endif%}
      {%endif%}
    {%endeach%}
  );

  return lockMaster;
}

void {{ cppClassName }}::{{ cppFunctionName }}Worker::Execute() {
  git_error_clear();

  {%if .|hasReturnType %}
    {{ return.cType }} result = {{ cFunctionName }}(
  {%else%}
    {{ cFunctionName }}(
  {%endif%}
    {%-- Insert Function Arguments --%}
    {%each args|argsInfo as arg %}
      {%-- turn the pointer into a ref --%}
      {%if arg.isReturn|and arg.cType|isDoublePointer %}&{%endif%}baton->{{ arg.name }}{%if not arg.lastArg %},{%endif%}
    {%endeach%}
  );

    {%if return.isResultOrError %}
      baton->error_code = result;
      if (result < GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

    {%elsif return.isErrorCode %}
      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

    {%elsif not return.cType == 'void' %}

      baton->result = result;

    {%endif%}
}

void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("{{ jsClassName }}.{{ jsFunctionName }}").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

  {%each args|argsInfo as arg %}
    {%if arg.shouldAlloc %}
      {%if not arg.isCppClassStringOrArray %}
      {%elsif arg | isOid %}
        if (baton->{{ arg.name}}NeedsFree) {
          baton->{{ arg.name}}NeedsFree = false;
          free((void*)baton->{{ arg.name }});
        }
      {%elsif arg.isCallbackFunction %}
        {%if not arg.payload.globalPayload %}
          delete baton->{{ arg.payload.name }};
        {%endif%}
      {%elsif arg.globalPayload %}
        delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
      {%else%}
        free((void*)baton->{{ arg.name }});
      {%endif%}
    {%endif%}
  {%endeach%}

  {%each args|argsInfo as arg %}
    {%if arg.isCppClassStringOrArray %}
      {%if arg.freeFunctionName %}
        {{ arg.freeFunctionName }}(baton->{{ arg.name }});
      {%elsif not arg.isConst%}
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%elsif arg | isOid %}
      if (baton->{{ arg.name}}NeedsFree) {
        baton->{{ arg.name}}NeedsFree = false;
        free((void *)baton->{{ arg.name }});
      }
    {%elsif arg.isCallbackFunction %}
      {%if not arg.payload.globalPayload %}
        delete baton->{{ arg.payload.name }};
      {%endif%}
    {%elsif arg.globalPayload %}
      delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
    {%endif%}
    {%if arg.cppClassName == "GitBuf" %}
      {%if cppFunctionName == "Set" %}
      {%else%}
        git_buf_dispose(baton->{{ arg.name }});
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%endif%}
  {%endeach%}

  delete baton;
}

void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() {
  {%if return.isResultOrError %}
    if (baton->error_code >= GIT_OK) {
  {%else%}
    if (baton->error_code == GIT_OK) {
  {%endif%}

  {%if return.isResultOrError %}
    v8::Local<v8::Value> result = Nan::New<v8::Number>(baton->error_code);

  {%elsif not .|returnsCount %}
    v8::Local<v8::Value> result = Nan::Undefined();
  {%else%}
    v8::Local<v8::Value> to;
    {%if .|returnsCount > 1 %}
      v8::Local<Object> result = Nan::New<Object>();
    {%endif%}
    {%each .|returnsInfo 0 1 as _return %}
      {%partial convertToV8 _return %}
      {%if .|returnsCount > 1 %}
        Nan::Set(result, Nan::New("{{ _return.returnNameOrName }}").ToLocalChecked(), to);
      {%endif%}
    {%endeach%}
    {%if .|returnsCount == 1 %}
      v8::Local<v8::Value> result = to;
    {%endif%}
  {%endif%}

    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method {{ jsFunctionName }} has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("{{ jsClassName }}.{{ jsFunctionName }}").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      std::queue< v8::Local<v8::Value> > workerArguments;
      {%each args|argsInfo as arg %}
        {%if not arg.isReturn %}
          {%if not arg.isSelf %}
            {%if not arg.isCallbackFunction %}
              workerArguments.push(GetFromPersistent("{{ arg.name }}"));
            {%endif%}
          {%endif%}
        {%endif%}
      {%endeach%}
      bool callbackFired = false;
      while(!workerArguments.empty()) {
        v8::Local<v8::Value> node = workerArguments.front();
        workerArguments.pop();

        if (
          !node->IsObject()
          || node->IsArray()
          || node->IsBooleanObject()
          || node->IsDate()
          || node->IsFunction()
          || node->IsNumberObject()
          || node->IsRegExp()
          || node->IsStringObject()
        ) {
          continue;
        }

        v8::Local<v8::Object> nodeObj = Nan::To<v8::Object>(node).ToLocalChecked();
        v8::Local<v8::Value> checkValue = GetPrivate(nodeObj, Nan::New("NodeGitPromiseError").ToLocalChecked());

        if (!checkValue.IsEmpty() && !checkValue->IsNull() && !checkValue->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            Nan::To<v8::Object>(checkValue).ToLocalChecked()
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
          break;
        }

        v8::Local<v8::Array> properties = Nan::GetPropertyNames(nodeObj).ToLocalChecked();
        for (unsigned int propIndex = 0; propIndex < properties->Length(); ++propIndex) {
          v8::Local<v8::String> propName = Nan::To<v8::String>(Nan::Get(properties, propIndex).ToLocalChecked()).ToLocalChecked();
          v8::Local<v8::Value> nodeToQueue = Nan::Get(nodeObj, propName).ToLocalChecked();
          if (!nodeToQueue->IsUndefined()) {
            workerArguments.push(nodeToQueue);
          }
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method {{ jsFunctionName }} has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("{{ jsClassName }}.{{ jsFunctionName }}").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

    {%each args|argsInfo as arg %}
      {%if arg.shouldAlloc %}
        {%if not arg.isCppClassStringOrArray %}
        {%elsif arg | isOid %}
          if (baton->{{ arg.name}}NeedsFree) {
            baton->{{ arg.name}}NeedsFree = false;
            free((void*)baton->{{ arg.name }});
          }
        {%elsif arg.isCallbackFunction %}
          {%if not arg.payload.globalPayload %}
            delete baton->{{ arg.payload.name }};
          {%endif%}
        {%elsif arg.globalPayload %}
          delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
        {%else%}
          free((void*)baton->{{ arg.name }});
        {%endif%}
      {%endif%}
    {%endeach%}
  }

  {%each args|argsInfo as arg %}
    {%if arg.isCppClassStringOrArray %}
      {%if arg.freeFunctionName %}
        {{ arg.freeFunctionName }}(baton->{{ arg.name }});
      {%elsif not arg.isConst%}
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%elsif arg | isOid %}
      if (baton->{{ arg.name}}NeedsFree) {
        baton->{{ arg.name}}NeedsFree = false;
        free((void *)baton->{{ arg.name }});
      }
    {%elsif arg.isCallbackFunction %}
      {%if not arg.payload.globalPayload %}
        delete baton->{{ arg.payload.name }};
      {%endif%}
    {%elsif arg.globalPayload %}
      delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
    {%endif%}
    {%if arg.cppClassName == "GitBuf" %}
      {%if cppFunctionName == "Set" %}
      {%else%}
        git_buf_dispose(baton->{{ arg.name }});
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%endif%}
  {%endeach%}

  delete baton;
}

{%partial callbackHelpers .%}
<commit_msg>Value initialize batons<commit_after>
{%partial doc .%}
NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
  {%partial guardArguments .%}
  if (info.Length() == {{args|jsArgsCount}} || !info[{{args|jsArgsCount}}]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  {{ cppFunctionName }}Baton* baton = new {{ cppFunctionName }}Baton();

  baton->error_code = GIT_OK;
  baton->error = NULL;

  {%each args|argsInfo as arg %}
    {%if arg.globalPayload %}
      {{ cppFunctionName }}_globalPayload* globalPayload = new {{ cppFunctionName }}_globalPayload;
    {%endif%}
  {%endeach%}

  {%each args|argsInfo as arg %}
    {%if not arg.isReturn %}
      {%if arg.isSelf %}
        baton->{{ arg.name }} = Nan::ObjectWrap::Unwrap<{{ arg.cppClassName }}>(info.This())->GetValue();
      {%elsif arg.isCallbackFunction %}
        if (!info[{{ arg.jsArg }}]->IsFunction()) {
          baton->{{ arg.name }} = NULL;
        {%if arg.payload.globalPayload %}
          globalPayload->{{ arg.name }} = NULL;
        {%else%}
          // NOTE this is a dead path
          baton->{{ arg.payload.name }} = NULL;
        {%endif%}
        }
        else {
          baton->{{ arg.name}} = {{ cppFunctionName }}_{{ arg.name }}_cppCallback;
          {%if arg.payload.globalPayload %}
            globalPayload->{{ arg.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As<Function>());
          {%else%}
            // NOTE this is a dead path
            baton->{{ arg.payload.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As<Function>());
          {%endif%}
        }
      {%elsif arg.payloadFor %}
        {%if arg.globalPayload %}
          baton->{{ arg.name }} = globalPayload;
        {%endif%}
      {%elsif arg.name %}
        {%partial convertFromV8 arg%}
        {%if not arg.payloadFor %}
          baton->{{ arg.name }} = from_{{ arg.name }};
          {%if arg | isOid %}
            baton->{{ arg.name }}NeedsFree = info[{{ arg.jsArg }}]->IsString();
          {%endif%}
        {%endif%}
      {%endif%}
    {%elsif arg.shouldAlloc %}
      baton->{{arg.name}} = ({{ arg.cType }})malloc(sizeof({{ arg.cType|replace '*' '' }}));
      {%if arg.cppClassName == "GitBuf" %}
        baton->{{arg.name}}->ptr = NULL;
        baton->{{arg.name}}->size = baton->{{arg.name}}->asize = 0;
      {%endif%}
    {%endif%}
  {%endeach%}

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[{{args|jsArgsCount}}]));
  {{ cppFunctionName }}Worker *worker = new {{ cppFunctionName }}Worker(baton, callback);

  {%each args|argsInfo as arg %}
    {%if not arg.isReturn %}
      {%if arg.isSelf %}
        worker->SaveToPersistent("{{ arg.name }}", info.This());
      {%elsif not arg.isCallbackFunction %}
        if (!info[{{ arg.jsArg }}]->IsUndefined() && !info[{{ arg.jsArg }}]->IsNull())
          worker->SaveToPersistent("{{ arg.name }}", Nan::To<v8::Object>(info[{{ arg.jsArg }}]).ToLocalChecked());
      {%endif%}
    {%endif%}
  {%endeach%}

  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster {{ cppClassName }}::{{ cppFunctionName }}Worker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
    {%each args|argsInfo as arg %}
      {%if arg.cType|isPointer%}
        {%if not arg.cType|isDoublePointer%}
          ,baton->{{ arg.name }}
        {%endif%}
      {%endif%}
    {%endeach%}
  );

  return lockMaster;
}

void {{ cppClassName }}::{{ cppFunctionName }}Worker::Execute() {
  git_error_clear();

  {%if .|hasReturnType %}
    {{ return.cType }} result = {{ cFunctionName }}(
  {%else%}
    {{ cFunctionName }}(
  {%endif%}
    {%-- Insert Function Arguments --%}
    {%each args|argsInfo as arg %}
      {%-- turn the pointer into a ref --%}
      {%if arg.isReturn|and arg.cType|isDoublePointer %}&{%endif%}baton->{{ arg.name }}{%if not arg.lastArg %},{%endif%}
    {%endeach%}
  );

    {%if return.isResultOrError %}
      baton->error_code = result;
      if (result < GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

    {%elsif return.isErrorCode %}
      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

    {%elsif not return.cType == 'void' %}

      baton->result = result;

    {%endif%}
}

void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("{{ jsClassName }}.{{ jsFunctionName }}").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

  {%each args|argsInfo as arg %}
    {%if arg.shouldAlloc %}
      {%if not arg.isCppClassStringOrArray %}
      {%elsif arg | isOid %}
        if (baton->{{ arg.name}}NeedsFree) {
          baton->{{ arg.name}}NeedsFree = false;
          free((void*)baton->{{ arg.name }});
        }
      {%elsif arg.isCallbackFunction %}
        {%if not arg.payload.globalPayload %}
          delete baton->{{ arg.payload.name }};
        {%endif%}
      {%elsif arg.globalPayload %}
        delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
      {%else%}
        free((void*)baton->{{ arg.name }});
      {%endif%}
    {%endif%}
  {%endeach%}

  {%each args|argsInfo as arg %}
    {%if arg.isCppClassStringOrArray %}
      {%if arg.freeFunctionName %}
        {{ arg.freeFunctionName }}(baton->{{ arg.name }});
      {%elsif not arg.isConst%}
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%elsif arg | isOid %}
      if (baton->{{ arg.name}}NeedsFree) {
        baton->{{ arg.name}}NeedsFree = false;
        free((void *)baton->{{ arg.name }});
      }
    {%elsif arg.isCallbackFunction %}
      {%if not arg.payload.globalPayload %}
        delete baton->{{ arg.payload.name }};
      {%endif%}
    {%elsif arg.globalPayload %}
      delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
    {%endif%}
    {%if arg.cppClassName == "GitBuf" %}
      {%if cppFunctionName == "Set" %}
      {%else%}
        git_buf_dispose(baton->{{ arg.name }});
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%endif%}
  {%endeach%}

  delete baton;
}

void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() {
  {%if return.isResultOrError %}
    if (baton->error_code >= GIT_OK) {
  {%else%}
    if (baton->error_code == GIT_OK) {
  {%endif%}

  {%if return.isResultOrError %}
    v8::Local<v8::Value> result = Nan::New<v8::Number>(baton->error_code);

  {%elsif not .|returnsCount %}
    v8::Local<v8::Value> result = Nan::Undefined();
  {%else%}
    v8::Local<v8::Value> to;
    {%if .|returnsCount > 1 %}
      v8::Local<Object> result = Nan::New<Object>();
    {%endif%}
    {%each .|returnsInfo 0 1 as _return %}
      {%partial convertToV8 _return %}
      {%if .|returnsCount > 1 %}
        Nan::Set(result, Nan::New("{{ _return.returnNameOrName }}").ToLocalChecked(), to);
      {%endif%}
    {%endeach%}
    {%if .|returnsCount == 1 %}
      v8::Local<v8::Value> result = to;
    {%endif%}
  {%endif%}

    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method {{ jsFunctionName }} has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("{{ jsClassName }}.{{ jsFunctionName }}").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      std::queue< v8::Local<v8::Value> > workerArguments;
      {%each args|argsInfo as arg %}
        {%if not arg.isReturn %}
          {%if not arg.isSelf %}
            {%if not arg.isCallbackFunction %}
              workerArguments.push(GetFromPersistent("{{ arg.name }}"));
            {%endif%}
          {%endif%}
        {%endif%}
      {%endeach%}
      bool callbackFired = false;
      while(!workerArguments.empty()) {
        v8::Local<v8::Value> node = workerArguments.front();
        workerArguments.pop();

        if (
          !node->IsObject()
          || node->IsArray()
          || node->IsBooleanObject()
          || node->IsDate()
          || node->IsFunction()
          || node->IsNumberObject()
          || node->IsRegExp()
          || node->IsStringObject()
        ) {
          continue;
        }

        v8::Local<v8::Object> nodeObj = Nan::To<v8::Object>(node).ToLocalChecked();
        v8::Local<v8::Value> checkValue = GetPrivate(nodeObj, Nan::New("NodeGitPromiseError").ToLocalChecked());

        if (!checkValue.IsEmpty() && !checkValue->IsNull() && !checkValue->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            Nan::To<v8::Object>(checkValue).ToLocalChecked()
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
          break;
        }

        v8::Local<v8::Array> properties = Nan::GetPropertyNames(nodeObj).ToLocalChecked();
        for (unsigned int propIndex = 0; propIndex < properties->Length(); ++propIndex) {
          v8::Local<v8::String> propName = Nan::To<v8::String>(Nan::Get(properties, propIndex).ToLocalChecked()).ToLocalChecked();
          v8::Local<v8::Value> nodeToQueue = Nan::Get(nodeObj, propName).ToLocalChecked();
          if (!nodeToQueue->IsUndefined()) {
            workerArguments.push(nodeToQueue);
          }
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method {{ jsFunctionName }} has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("{{ jsClassName }}.{{ jsFunctionName }}").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

    {%each args|argsInfo as arg %}
      {%if arg.shouldAlloc %}
        {%if not arg.isCppClassStringOrArray %}
        {%elsif arg | isOid %}
          if (baton->{{ arg.name}}NeedsFree) {
            baton->{{ arg.name}}NeedsFree = false;
            free((void*)baton->{{ arg.name }});
          }
        {%elsif arg.isCallbackFunction %}
          {%if not arg.payload.globalPayload %}
            delete baton->{{ arg.payload.name }};
          {%endif%}
        {%elsif arg.globalPayload %}
          delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
        {%else%}
          free((void*)baton->{{ arg.name }});
        {%endif%}
      {%endif%}
    {%endeach%}
  }

  {%each args|argsInfo as arg %}
    {%if arg.isCppClassStringOrArray %}
      {%if arg.freeFunctionName %}
        {{ arg.freeFunctionName }}(baton->{{ arg.name }});
      {%elsif not arg.isConst%}
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%elsif arg | isOid %}
      if (baton->{{ arg.name}}NeedsFree) {
        baton->{{ arg.name}}NeedsFree = false;
        free((void *)baton->{{ arg.name }});
      }
    {%elsif arg.isCallbackFunction %}
      {%if not arg.payload.globalPayload %}
        delete baton->{{ arg.payload.name }};
      {%endif%}
    {%elsif arg.globalPayload %}
      delete ({{ cppFunctionName}}_globalPayload*)baton->{{ arg.name }};
    {%endif%}
    {%if arg.cppClassName == "GitBuf" %}
      {%if cppFunctionName == "Set" %}
      {%else%}
        git_buf_dispose(baton->{{ arg.name }});
        free((void *)baton->{{ arg.name }});
      {%endif%}
    {%endif%}
  {%endeach%}

  delete baton;
}

{%partial callbackHelpers .%}
<|endoftext|>


<commit_before>/**
 *  @file bigfixstats.cpp
 *  @brief Converts BigFix deployment reports into Atlassian Confluence tables
 */

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Michael Maraya
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include "bigfix/bigfixstats.h"

/**
 *  @brief Converts BigFix deployment reports into text for updating Atlassian
 *         Confluence tables
 *  @param argc number of command-line arguments
 *  @param argv array of command-line arguments
 *  @retval int returns 0 upon successful program completion, non-zero otherwise
 */
int main(int argc, const char * argv[]) {
  // load arguments into vector<string> so we can use std::find
  std::vector<std::string> args;
  std::vector<std::string>::iterator it;
  for (int i = 1; i < argc; ++i) {
    args.push_back(argv[i]);
  }
  // display -h help
  it = std::find(args.begin(), args.end(), "-h");
  if ((argc == 1) || (it != args.end())) {
    usage();
    return 0;
  }
  // use -i input file
  std::string infile {};
  it = std::find(args.begin(), args.end(), "-i");
  if (it != args.end()) {
    if (next(it) != args.end()) {
      infile = *next(it);
    } else {
      printf("%s: option -i requires an argument\n", bf::kProgramName.c_str());
      usage();
      return 1;
    }
  }
  // open input file
  std::ifstream fs(infile);
  if (fs.is_open()) {
    std::string line {};
    while (std::getline(fs, line)) {
      if (line.compare(0, bf::kRecord.length(), bf::kRecord) == 0) {
        // read records
        std::size_t start = line.find(bf::kStart, 0), end {0};
        while (start != std::string::npos) {
          std::string group {}, count {};
          // read computer group
          end = line.find(bf::kEnd, start);
          if (end != std::string::npos) {
            start += bf::kStart.length();
            group = line.substr(start, end - start);
            printf("Group: %s\t", group.c_str());
          }
          // read computer count
          start = line.find(bf::kStart, start + bf::kStart.length());
          end = line.find(bf::kEnd, start);
          if (end != std::string::npos) {
            start += bf::kStart.length();
            count = line.substr(start, end - start);
            printf("Count: %s\n", count.c_str());
          }
          start = line.find(bf::kStart, start + bf::kStart.length());
        }
      }
    }
    fs.close();
  } else {
    printf("Error: Could not open file %s", infile.c_str());
    return 1;
  }
}

/**
 *  @details Display program name, version, and usage
 */
void usage() {
  printf("%s, version %u.%u\n\n", bf::kProgramName.c_str(), bf::kMajorVersion,
         bf::kMinorVersion);
  printf("usage: %s [-h] [-i filename]\n", bf::kProgramName.c_str());
  printf("-h display usage\n");
  printf("-i filename\n\n");
}
<commit_msg>ComputerGroup class definitions and display totals<commit_after>/**
 *  @file bigfixstats.cpp
 *  @brief Converts BigFix deployment reports into Atlassian Confluence tables
 */

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Michael Maraya
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include "bigfix/bigfixstats.h"

std::string ComputerGroup::name() const {
  return name_;
}

uint16_t ComputerGroup::current() const {
  return current_;
}

uint16_t ComputerGroup::target() const {
  return target_;
}

uint8_t ComputerGroup::percent() const {
  return current_ / target_ * 100;
}

void ComputerGroup::set_name(std::string name) {
  name_ = name;
}

void ComputerGroup::set_current(uint16_t current) {
  current_ = current;
}

void ComputerGroup::set_target(uint16_t target) {
  target_ = target;
}

/**
 *  @brief Converts BigFix deployment reports into text for updating Atlassian
 *         Confluence tables
 *  @param argc number of command-line arguments
 *  @param argv array of command-line arguments
 *  @retval int returns 0 upon successful program completion, non-zero otherwise
 */
int main(int argc, const char * argv[]) {
  // load arguments into vector<string> so we can use std::find
  std::vector<std::string> args;
  std::vector<std::string>::iterator it;
  for (int i = 1; i < argc; ++i) {
    args.push_back(argv[i]);
  }
  // display -h help
  it = std::find(args.begin(), args.end(), "-h");
  if ((argc == 1) || (it != args.end())) {
    usage();
    return 0;
  }
  // use -i input file
  std::string infile {};
  it = std::find(args.begin(), args.end(), "-i");
  if (it != args.end()) {
    if (next(it) != args.end()) {
      infile = *next(it);
    } else {
      printf("%s: option -i requires an argument\n", bf::kProgramName.c_str());
      usage();
      return 1;
    }
  }
  // open input file
  std::vector<ComputerGroup> groups;
  std::ifstream fs(infile);
  if (fs.is_open()) {
    std::string line {};
    while (std::getline(fs, line)) {
      if (line.compare(0, bf::kRecord.length(), bf::kRecord) == 0) {
        // read records
        std::size_t start = line.find(bf::kStart, 0), end {0};
        while (start != std::string::npos) {
          uint16_t count {0};
          std::string group {}, current {};
          // read computer group
          end = line.find(bf::kEnd, start);
          if (end != std::string::npos) {
            start += bf::kStart.length();
            group = line.substr(start, end - start);
            printf("Group: %s\t", group.c_str());
          }
          // read computer count
          start = line.find(bf::kStart, start + bf::kStart.length());
          end = line.find(bf::kEnd, start);
          if (end != std::string::npos) {
            start += bf::kStart.length();
            current = line.substr(start, end - start);
            count = std::stoi(current);
            printf("Count: %s\n", current.c_str());
          }
          // create new computer group
          ComputerGroup cg = ComputerGroup();
          cg.set_name(group);
          cg.set_current(count);
          groups.push_back(cg);
          // read next computer group
          start = line.find(bf::kStart, start + bf::kStart.length());
        }
      }
    }
    fs.close();
  } else {
    printf("Error: Could not open file %s", infile.c_str());
    return 1;
  }
  // compute total
  uint16_t total {0};
  for (auto cg : groups) {
    total += cg.current();
  }
  printf("Total: %d\n", total);
}

/**
 *  @details Display program name, version, and usage
 */
void usage() {
  printf("%s, version %u.%u\n\n", bf::kProgramName.c_str(), bf::kMajorVersion,
         bf::kMinorVersion);
  printf("usage: %s [-h] [-i filename]\n", bf::kProgramName.c_str());
  printf("-h display usage\n");
  printf("-i filename\n\n");
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
#include <QtCore/qabstractitemmodel.h>
#include <QDebug>
#include "../../shared/util.h"

#if defined (Q_OS_WIN)
#include <qt_windows.h>
#endif

// From qquickfolderlistmodel.h
const int FileNameRole = Qt::UserRole+1;
const int FilePathRole = Qt::UserRole+2;
enum SortField { Unsorted, Name, Time, Size, Type };

class tst_qquickfolderlistmodel : public QQmlDataTest
{
    Q_OBJECT
public:
    tst_qquickfolderlistmodel() : removeStart(0), removeEnd(0) {}

public slots:
    void removed(const QModelIndex &, int start, int end) {
        removeStart = start;
        removeEnd = end;
    }

private slots:
    void basicProperties();
    void showFiles();
    void resetFiltering();
    void refresh();
#if defined (Q_OS_WIN) && !defined (Q_OS_WINCE)
    // WinCE does not have drive concept, so lets execute this test only on desktop Windows.
    void changeDrive();
#endif
    void showDotAndDotDot();
    void showDotAndDotDot_data();

private:
    void checkNoErrors(const QQmlComponent& component);
    QQmlEngine engine;

    int removeStart;
    int removeEnd;
};

void tst_qquickfolderlistmodel::checkNoErrors(const QQmlComponent& component)
{
    // Wait until the component is ready
    QTRY_VERIFY(component.isReady() || component.isError());

    if (component.isError()) {
        QList<QQmlError> errors = component.errors();
        for (int ii = 0; ii < errors.count(); ++ii) {
            const QQmlError &error = errors.at(ii);
            QByteArray errorStr = QByteArray::number(error.line()) + ":" +
                                  QByteArray::number(error.column()) + ":" +
                                  error.description().toUtf8();
            qWarning() << errorStr;
        }
    }
    QVERIFY(!component.isError());
}

void tst_qquickfolderlistmodel::basicProperties()
{
    QQmlComponent component(&engine, testFileUrl("basic.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", dataDirectoryUrl());
    QTRY_COMPARE(flm->property("count").toInt(),5); // wait for refresh
    QCOMPARE(flm->property("folder").toUrl(), dataDirectoryUrl());
    QCOMPARE(flm->property("parentFolder").toUrl(), QUrl::fromLocalFile(QDir(directory()).canonicalPath()));
    QCOMPARE(flm->property("sortField").toInt(), int(Name));
    QCOMPARE(flm->property("nameFilters").toStringList(), QStringList() << "*.qml");
    QCOMPARE(flm->property("sortReversed").toBool(), false);
    QCOMPARE(flm->property("showFiles").toBool(), true);
    QCOMPARE(flm->property("showDirs").toBool(), true);
    QCOMPARE(flm->property("showDotAndDotDot").toBool(), false);
    QCOMPARE(flm->property("showOnlyReadable").toBool(), false);
    QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("basic.qml"));
    QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String("dummy.qml"));

    flm->setProperty("folder",QUrl::fromLocalFile(""));
    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(""));
}

void tst_qquickfolderlistmodel::showFiles()
{
    QQmlComponent component(&engine, testFileUrl("basic.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", dataDirectoryUrl());
    QTRY_COMPARE(flm->property("count").toInt(), 5); // wait for refresh
    QCOMPARE(flm->property("showFiles").toBool(), true);

    flm->setProperty("showFiles", false);
    QCOMPARE(flm->property("showFiles").toBool(), false);
    QTRY_COMPARE(flm->property("count").toInt(), 1); // wait for refresh
}

void tst_qquickfolderlistmodel::resetFiltering()
{
    // see QTBUG-17837
    QQmlComponent component(&engine, testFileUrl("resetFiltering.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
            this, SLOT(removed(const QModelIndex&,int,int)));

    flm->setProperty("folder", testFileUrl("resetfiltering"));
    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
    int count = flm->rowCount();
    QCOMPARE(removeStart, 0);
    QCOMPARE(removeEnd, count-1);

    flm->setProperty("folder", testFileUrl("resetfiltering/innerdir"));
    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test2.txt" visible
    count = flm->rowCount();
    QCOMPARE(removeStart, 0);
    QCOMPARE(removeEnd, count-1);

    flm->setProperty("folder", testFileUrl("resetfiltering"));
    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
    count = flm->rowCount();
    QCOMPARE(removeStart, 0);
    QCOMPARE(removeEnd, count-1);
}

void tst_qquickfolderlistmodel::refresh()
{
    QQmlComponent component(&engine, testFileUrl("basic.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", dataDirectoryUrl());
    QTRY_COMPARE(flm->property("count").toInt(),5); // wait for refresh

    int count = flm->rowCount();

    connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
            this, SLOT(removed(const QModelIndex&,int,int)));

    flm->setProperty("sortReversed", true);

    QTRY_COMPARE(removeStart, 0);
    QTRY_COMPARE(removeEnd, count-1); // wait for refresh
}

#if defined (Q_OS_WIN) && !defined (Q_OS_WINCE)
void tst_qquickfolderlistmodel::changeDrive()
{
    QSKIP("QTBUG-26728");
    class DriveMapper
    {
    public:
        DriveMapper(const QString &dataDir)
        {
            size_t stringLen = dataDir.length();
            targetPath = new wchar_t[stringLen+1];
            dataDir.toWCharArray(targetPath);
            targetPath[stringLen] = 0;

            DefineDosDevice(DDD_NO_BROADCAST_SYSTEM, L"X:", targetPath);
        }

        ~DriveMapper()
        {
            DefineDosDevice(DDD_EXACT_MATCH_ON_REMOVE | DDD_NO_BROADCAST_SYSTEM | DDD_REMOVE_DEFINITION, L"X:", targetPath);
            delete [] targetPath;
        }

    private:
        wchar_t *targetPath;
    };

    QString dataDir = testFile(0);
    DriveMapper dm(dataDir);
    QQmlComponent component(&engine, testFileUrl("basic.qml"));

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    QSignalSpy folderChangeSpy(flm, SIGNAL(folderChanged()));

    flm->setProperty("folder",QUrl::fromLocalFile(dataDir));
    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(dataDir));
    QTRY_VERIFY(folderChangeSpy.count() == 1);

    flm->setProperty("folder",QUrl::fromLocalFile("X:/resetfiltering/"));
    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile("X:/resetfiltering/"));
    QTRY_VERIFY(folderChangeSpy.count() == 2);
}
#endif

void tst_qquickfolderlistmodel::showDotAndDotDot()
{
    QFETCH(QUrl, folder);
    QFETCH(QUrl, rootFolder);
    QFETCH(bool, showDotAndDotDot);
    QFETCH(bool, showDot);
    QFETCH(bool, showDotDot);

    QQmlComponent component(&engine, testFileUrl("showDotAndDotDot.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", folder);
    flm->setProperty("rootFolder", rootFolder);
    flm->setProperty("showDotAndDotDot", showDotAndDotDot);

    int count = 5;
    if (showDot) count++;
    if (showDotDot) count++;
    QTRY_COMPARE(flm->property("count").toInt(), count); // wait for refresh

    if (showDot)
        QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("."));
    if (showDotDot)
        QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String(".."));
}

void tst_qquickfolderlistmodel::showDotAndDotDot_data()
{
    QTest::addColumn<QUrl>("folder");
    QTest::addColumn<QUrl>("rootFolder");
    QTest::addColumn<bool>("showDotAndDotDot");
    QTest::addColumn<bool>("showDot");
    QTest::addColumn<bool>("showDotDot");

    QTest::newRow("false") << dataDirectoryUrl() << QUrl() << false << false << false;
    QTest::newRow("true") << dataDirectoryUrl() << QUrl() << true << true << true;
    QTest::newRow("true but root") << dataDirectoryUrl() << dataDirectoryUrl() << true << true << false;

}

QTEST_MAIN(tst_qquickfolderlistmodel)

#include "tst_qquickfolderlistmodel.moc"
<commit_msg>Fix race condition in tst_QQuickFolderListModel::basicProperties<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtCore/qdir.h>
#include <QtCore/qfile.h>
#include <QtCore/qabstractitemmodel.h>
#include <QDebug>
#include "../../shared/util.h"

#if defined (Q_OS_WIN)
#include <qt_windows.h>
#endif

static bool waitForSignal(QObject* obj, const char* signal, int timeout = 10000)
{
    QEventLoop loop;
    QObject::connect(obj, signal, &loop, SLOT(quit()));
    QTimer timer;
    QSignalSpy timeoutSpy(&timer, SIGNAL(timeout()));
    if (timeout > 0) {
        QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
        timer.setSingleShot(true);
        timer.start(timeout);
    }
    loop.exec();
    return timeoutSpy.isEmpty();
}

// From qquickfolderlistmodel.h
const int FileNameRole = Qt::UserRole+1;
const int FilePathRole = Qt::UserRole+2;
enum SortField { Unsorted, Name, Time, Size, Type };

class tst_qquickfolderlistmodel : public QQmlDataTest
{
    Q_OBJECT
public:
    tst_qquickfolderlistmodel() : removeStart(0), removeEnd(0) {}

public slots:
    void removed(const QModelIndex &, int start, int end) {
        removeStart = start;
        removeEnd = end;
    }

private slots:
    void basicProperties();
    void showFiles();
    void resetFiltering();
    void refresh();
#if defined (Q_OS_WIN) && !defined (Q_OS_WINCE)
    // WinCE does not have drive concept, so lets execute this test only on desktop Windows.
    void changeDrive();
#endif
    void showDotAndDotDot();
    void showDotAndDotDot_data();

private:
    void checkNoErrors(const QQmlComponent& component);
    QQmlEngine engine;

    int removeStart;
    int removeEnd;
};

void tst_qquickfolderlistmodel::checkNoErrors(const QQmlComponent& component)
{
    // Wait until the component is ready
    QTRY_VERIFY(component.isReady() || component.isError());

    if (component.isError()) {
        QList<QQmlError> errors = component.errors();
        for (int ii = 0; ii < errors.count(); ++ii) {
            const QQmlError &error = errors.at(ii);
            QByteArray errorStr = QByteArray::number(error.line()) + ":" +
                                  QByteArray::number(error.column()) + ":" +
                                  error.description().toUtf8();
            qWarning() << errorStr;
        }
    }
    QVERIFY(!component.isError());
}

void tst_qquickfolderlistmodel::basicProperties()
{
    QQmlComponent component(&engine, testFileUrl("basic.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", dataDirectoryUrl());
    ::waitForSignal(flm, SIGNAL(folderChanged()), 0);
    QCOMPARE(flm->property("count").toInt(), 5);
    QCOMPARE(flm->property("folder").toUrl(), dataDirectoryUrl());
    QCOMPARE(flm->property("parentFolder").toUrl(), QUrl::fromLocalFile(QDir(directory()).canonicalPath()));
    QCOMPARE(flm->property("sortField").toInt(), int(Name));
    QCOMPARE(flm->property("nameFilters").toStringList(), QStringList() << "*.qml");
    QCOMPARE(flm->property("sortReversed").toBool(), false);
    QCOMPARE(flm->property("showFiles").toBool(), true);
    QCOMPARE(flm->property("showDirs").toBool(), true);
    QCOMPARE(flm->property("showDotAndDotDot").toBool(), false);
    QCOMPARE(flm->property("showOnlyReadable").toBool(), false);
    QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("basic.qml"));
    QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String("dummy.qml"));

    flm->setProperty("folder",QUrl::fromLocalFile(""));
    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(""));
}

void tst_qquickfolderlistmodel::showFiles()
{
    QQmlComponent component(&engine, testFileUrl("basic.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", dataDirectoryUrl());
    QTRY_COMPARE(flm->property("count").toInt(), 5); // wait for refresh
    QCOMPARE(flm->property("showFiles").toBool(), true);

    flm->setProperty("showFiles", false);
    QCOMPARE(flm->property("showFiles").toBool(), false);
    QTRY_COMPARE(flm->property("count").toInt(), 1); // wait for refresh
}

void tst_qquickfolderlistmodel::resetFiltering()
{
    // see QTBUG-17837
    QQmlComponent component(&engine, testFileUrl("resetFiltering.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
            this, SLOT(removed(const QModelIndex&,int,int)));

    flm->setProperty("folder", testFileUrl("resetfiltering"));
    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
    int count = flm->rowCount();
    QCOMPARE(removeStart, 0);
    QCOMPARE(removeEnd, count-1);

    flm->setProperty("folder", testFileUrl("resetfiltering/innerdir"));
    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test2.txt" visible
    count = flm->rowCount();
    QCOMPARE(removeStart, 0);
    QCOMPARE(removeEnd, count-1);

    flm->setProperty("folder", testFileUrl("resetfiltering"));
    QTRY_COMPARE(flm->property("count").toInt(),1); // should just be "test.txt" visible
    count = flm->rowCount();
    QCOMPARE(removeStart, 0);
    QCOMPARE(removeEnd, count-1);
}

void tst_qquickfolderlistmodel::refresh()
{
    QQmlComponent component(&engine, testFileUrl("basic.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", dataDirectoryUrl());
    QTRY_COMPARE(flm->property("count").toInt(),5); // wait for refresh

    int count = flm->rowCount();

    connect(flm, SIGNAL(rowsRemoved(const QModelIndex&,int,int)),
            this, SLOT(removed(const QModelIndex&,int,int)));

    flm->setProperty("sortReversed", true);

    QTRY_COMPARE(removeStart, 0);
    QTRY_COMPARE(removeEnd, count-1); // wait for refresh
}

#if defined (Q_OS_WIN) && !defined (Q_OS_WINCE)
void tst_qquickfolderlistmodel::changeDrive()
{
    QSKIP("QTBUG-26728");
    class DriveMapper
    {
    public:
        DriveMapper(const QString &dataDir)
        {
            size_t stringLen = dataDir.length();
            targetPath = new wchar_t[stringLen+1];
            dataDir.toWCharArray(targetPath);
            targetPath[stringLen] = 0;

            DefineDosDevice(DDD_NO_BROADCAST_SYSTEM, L"X:", targetPath);
        }

        ~DriveMapper()
        {
            DefineDosDevice(DDD_EXACT_MATCH_ON_REMOVE | DDD_NO_BROADCAST_SYSTEM | DDD_REMOVE_DEFINITION, L"X:", targetPath);
            delete [] targetPath;
        }

    private:
        wchar_t *targetPath;
    };

    QString dataDir = testFile(0);
    DriveMapper dm(dataDir);
    QQmlComponent component(&engine, testFileUrl("basic.qml"));

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    QSignalSpy folderChangeSpy(flm, SIGNAL(folderChanged()));

    flm->setProperty("folder",QUrl::fromLocalFile(dataDir));
    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile(dataDir));
    QTRY_VERIFY(folderChangeSpy.count() == 1);

    flm->setProperty("folder",QUrl::fromLocalFile("X:/resetfiltering/"));
    QCOMPARE(flm->property("folder").toUrl(), QUrl::fromLocalFile("X:/resetfiltering/"));
    QTRY_VERIFY(folderChangeSpy.count() == 2);
}
#endif

void tst_qquickfolderlistmodel::showDotAndDotDot()
{
    QFETCH(QUrl, folder);
    QFETCH(QUrl, rootFolder);
    QFETCH(bool, showDotAndDotDot);
    QFETCH(bool, showDot);
    QFETCH(bool, showDotDot);

    QQmlComponent component(&engine, testFileUrl("showDotAndDotDot.qml"));
    checkNoErrors(component);

    QAbstractListModel *flm = qobject_cast<QAbstractListModel*>(component.create());
    QVERIFY(flm != 0);

    flm->setProperty("folder", folder);
    flm->setProperty("rootFolder", rootFolder);
    flm->setProperty("showDotAndDotDot", showDotAndDotDot);

    int count = 5;
    if (showDot) count++;
    if (showDotDot) count++;
    QTRY_COMPARE(flm->property("count").toInt(), count); // wait for refresh

    if (showDot)
        QCOMPARE(flm->data(flm->index(0),FileNameRole).toString(), QLatin1String("."));
    if (showDotDot)
        QCOMPARE(flm->data(flm->index(1),FileNameRole).toString(), QLatin1String(".."));
}

void tst_qquickfolderlistmodel::showDotAndDotDot_data()
{
    QTest::addColumn<QUrl>("folder");
    QTest::addColumn<QUrl>("rootFolder");
    QTest::addColumn<bool>("showDotAndDotDot");
    QTest::addColumn<bool>("showDot");
    QTest::addColumn<bool>("showDotDot");

    QTest::newRow("false") << dataDirectoryUrl() << QUrl() << false << false << false;
    QTest::newRow("true") << dataDirectoryUrl() << QUrl() << true << true << true;
    QTest::newRow("true but root") << dataDirectoryUrl() << dataDirectoryUrl() << true << true << false;

}

QTEST_MAIN(tst_qquickfolderlistmodel)

#include "tst_qquickfolderlistmodel.moc"
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/nacl_host/nacl_broker_service_win.h"

#include "chrome/browser/nacl_host/nacl_process_host.h"

NaClBrokerService* NaClBrokerService::GetInstance() {
  return Singleton<NaClBrokerService>::get();
}

NaClBrokerService::NaClBrokerService()
    : loaders_running_(0) {
}

bool NaClBrokerService::StartBroker() {
  NaClBrokerHost* broker_host = new NaClBrokerHost;
  if (!broker_host->Init()) {
    delete broker_host;
    return false;
  }
  return true;
}

bool NaClBrokerService::LaunchLoader(NaClProcessHost* nacl_process_host,
                                     const std::wstring& loader_channel_id) {
  // Add task to the list
  pending_launches_[loader_channel_id] = nacl_process_host;
  NaClBrokerHost* broker_host = GetBrokerHost();

  if (!broker_host) {
    if (!StartBroker())
      return false;
    broker_host = GetBrokerHost();
  }
  broker_host->LaunchLoader(loader_channel_id);

  return true;
}

void NaClBrokerService::OnLoaderLaunched(const std::wstring& channel_id,
                                         base::ProcessHandle handle) {
  NaClProcessHost* client;
  PendingLaunchesMap::iterator it = pending_launches_.find(channel_id);
  if (pending_launches_.end() == it)
    NOTREACHED();

  client = it->second;
  client->OnProcessLaunchedByBroker(handle);
  pending_launches_.erase(it);
  ++loaders_running_;
}

void NaClBrokerService::OnLoaderDied() {
  --loaders_running_;
  // Stop the broker only if there are no loaders running or being launched.
  NaClBrokerHost* broker_host = GetBrokerHost();
  if (loaders_running_ + pending_launches_.size() == 0 && broker_host != NULL) {
    broker_host->StopBroker();
  }
}

NaClBrokerHost* NaClBrokerService::GetBrokerHost() {
  for (BrowserChildProcessHost::Iterator iter(
           ChildProcessInfo::NACL_BROKER_PROCESS);
       !iter.Done();
       ++iter) {
    NaClBrokerHost* broker_host = static_cast<NaClBrokerHost*>(*iter);
    return broker_host;
  }
  return NULL;
}
<commit_msg>Coverity: Remove unneeded for loop in NaClBrokerService::GetBrokerHost.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/nacl_host/nacl_broker_service_win.h"

#include "chrome/browser/nacl_host/nacl_process_host.h"

NaClBrokerService* NaClBrokerService::GetInstance() {
  return Singleton<NaClBrokerService>::get();
}

NaClBrokerService::NaClBrokerService()
    : loaders_running_(0) {
}

bool NaClBrokerService::StartBroker() {
  NaClBrokerHost* broker_host = new NaClBrokerHost;
  if (!broker_host->Init()) {
    delete broker_host;
    return false;
  }
  return true;
}

bool NaClBrokerService::LaunchLoader(NaClProcessHost* nacl_process_host,
                                     const std::wstring& loader_channel_id) {
  // Add task to the list
  pending_launches_[loader_channel_id] = nacl_process_host;
  NaClBrokerHost* broker_host = GetBrokerHost();

  if (!broker_host) {
    if (!StartBroker())
      return false;
    broker_host = GetBrokerHost();
  }
  broker_host->LaunchLoader(loader_channel_id);

  return true;
}

void NaClBrokerService::OnLoaderLaunched(const std::wstring& channel_id,
                                         base::ProcessHandle handle) {
  NaClProcessHost* client;
  PendingLaunchesMap::iterator it = pending_launches_.find(channel_id);
  if (pending_launches_.end() == it)
    NOTREACHED();

  client = it->second;
  client->OnProcessLaunchedByBroker(handle);
  pending_launches_.erase(it);
  ++loaders_running_;
}

void NaClBrokerService::OnLoaderDied() {
  --loaders_running_;
  // Stop the broker only if there are no loaders running or being launched.
  NaClBrokerHost* broker_host = GetBrokerHost();
  if (loaders_running_ + pending_launches_.size() == 0 && broker_host != NULL) {
    broker_host->StopBroker();
  }
}

NaClBrokerHost* NaClBrokerService::GetBrokerHost() {
  BrowserChildProcessHost::Iterator iter(ChildProcessInfo::NACL_BROKER_PROCESS);
  if (iter.Done())
    return NULL;
  NaClBrokerHost* broker_host = static_cast<NaClBrokerHost*>(*iter);
  return broker_host;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/privacy_blacklist/blacklist_store.h"

#include <cstdio>

#include "base/basictypes.h"
#include "base/file_util.h"

namespace {

const char cookie[] = "GCPBL100";

}

void BlacklistStoreOutput::WriteUInt(uint32 i) {
  fwrite(reinterpret_cast<char*>(&i), 1, sizeof(uint32), file_);
}

void BlacklistStoreOutput::WriteString(const std::string& s) {
  uint32 n = s.size();
  fwrite(reinterpret_cast<char*>(&n), 1, sizeof(uint32), file_);
  fwrite(s.c_str(), 1, s.size(), file_);
}

BlacklistStoreOutput::BlacklistStoreOutput(FILE* file) : file_(file) {
  fwrite(cookie, 1, sizeof(cookie), file_);
}

BlacklistStoreOutput::~BlacklistStoreOutput() {
  file_util::CloseFile(file_);
}

void BlacklistStoreOutput::ReserveProviders(uint32 num) {
  WriteUInt(num);
}

void BlacklistStoreOutput::StoreProvider(const std::string& name,
                                         const std::string& url) {
  WriteString(name);
  WriteString(url);
}

void BlacklistStoreOutput::ReserveEntries(uint32 num) {
  WriteUInt(num);
}

void BlacklistStoreOutput::StoreEntry(const std::string& pattern,
                                      uint32 attributes,
                                      const std::vector<std::string>& types,
                                      uint32 provider) {
  WriteString(pattern);
  WriteUInt(attributes);
  WriteUInt(types.size());
  for (uint32 i = 0; i < types.size(); ++i)
    WriteString(types[i]);
  WriteUInt(provider);
}

uint32 BlacklistStoreInput::ReadUInt() {
  char buf[sizeof(uint32)];
  fread(buf, 1, sizeof(uint32), file_);
  return *reinterpret_cast<uint32*>(buf);
}

std::string BlacklistStoreInput::ReadString() {
  uint32 size = ReadUInt();

  // Too long strings are not allowed.
  if (size > 8192) {
    return std::string();
  }

  char buf[8192];
  fread(buf, 1, size, file_);
  return std::string(buf, size);
}

BlacklistStoreInput::BlacklistStoreInput(FILE* file) : file_(file) {
  char buf[sizeof(cookie)];
  fread(buf, 1, sizeof(cookie), file_);
}

BlacklistStoreInput::~BlacklistStoreInput() {
  file_util::CloseFile(file_);
}

uint32 BlacklistStoreInput::ReadNumProviders() {
  return ReadUInt();
}

void BlacklistStoreInput::ReadProvider(std::string* name, std::string* url) {
  *name = ReadString();
  *url = ReadString();
}

uint32 BlacklistStoreInput::ReadNumEntries() {
  return ReadUInt();
}

void BlacklistStoreInput::ReadEntry(std::string* pattern,
                                    uint32* attributes,
                                    std::vector<std::string>* types,
                                    uint32* provider) {
  *pattern = ReadString();
  *attributes = ReadUInt();
  if (uint32 n = ReadUInt()) {
    while (n--)
      types->push_back(ReadString());
  }
  *provider = ReadUInt();
}
<commit_msg>GCC > 4.2 fix: check return values for fread<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/privacy_blacklist/blacklist_store.h"

#include <cstdio>

#include "base/basictypes.h"
#include "base/file_util.h"

namespace {

const char cookie[] = "GCPBL100";

}

void BlacklistStoreOutput::WriteUInt(uint32 i) {
  fwrite(reinterpret_cast<char*>(&i), 1, sizeof(uint32), file_);
}

void BlacklistStoreOutput::WriteString(const std::string& s) {
  uint32 n = s.size();
  fwrite(reinterpret_cast<char*>(&n), 1, sizeof(uint32), file_);
  fwrite(s.c_str(), 1, s.size(), file_);
}

BlacklistStoreOutput::BlacklistStoreOutput(FILE* file) : file_(file) {
  fwrite(cookie, 1, sizeof(cookie), file_);
}

BlacklistStoreOutput::~BlacklistStoreOutput() {
  file_util::CloseFile(file_);
}

void BlacklistStoreOutput::ReserveProviders(uint32 num) {
  WriteUInt(num);
}

void BlacklistStoreOutput::StoreProvider(const std::string& name,
                                         const std::string& url) {
  WriteString(name);
  WriteString(url);
}

void BlacklistStoreOutput::ReserveEntries(uint32 num) {
  WriteUInt(num);
}

void BlacklistStoreOutput::StoreEntry(const std::string& pattern,
                                      uint32 attributes,
                                      const std::vector<std::string>& types,
                                      uint32 provider) {
  WriteString(pattern);
  WriteUInt(attributes);
  WriteUInt(types.size());
  for (uint32 i = 0; i < types.size(); ++i)
    WriteString(types[i]);
  WriteUInt(provider);
}

uint32 BlacklistStoreInput::ReadUInt() {
  char buf[sizeof(uint32)];
  if (fread(buf, 1, sizeof(uint32), file_) != sizeof(uint32))
    return 0;
  return *reinterpret_cast<uint32*>(buf);
}

std::string BlacklistStoreInput::ReadString() {
  uint32 size = ReadUInt();

  // Too long strings are not allowed.
  if (size > 8192) {
    return std::string();
  }

  char buf[8192];
  if (fread(buf, 1, size, file_) != size)
    return std::string();
  return std::string(buf, size);
}

BlacklistStoreInput::BlacklistStoreInput(FILE* file) : file_(file) {
  fseek(file_, sizeof(cookie), SEEK_CUR);
}

BlacklistStoreInput::~BlacklistStoreInput() {
  file_util::CloseFile(file_);
}

uint32 BlacklistStoreInput::ReadNumProviders() {
  return ReadUInt();
}

void BlacklistStoreInput::ReadProvider(std::string* name, std::string* url) {
  *name = ReadString();
  *url = ReadString();
}

uint32 BlacklistStoreInput::ReadNumEntries() {
  return ReadUInt();
}

void BlacklistStoreInput::ReadEntry(std::string* pattern,
                                    uint32* attributes,
                                    std::vector<std::string>* types,
                                    uint32* provider) {
  *pattern = ReadString();
  *attributes = ReadUInt();
  if (uint32 n = ReadUInt()) {
    while (n--)
      types->push_back(ReadString());
  }
  *provider = ReadUInt();
}
<|endoftext|>


<commit_before>/*****************************************************************************
 * directslider.hpp : A slider that goes where you click
 ****************************************************************************
 * Copyright (C) 2006 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          with precious help from ahigerd on #qt@freenode
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/

#ifndef _DIRECTSLIDER_H_
#define _DIRECTSLIDER_H_

#include <QSlider>
#include <QMouseEvent>
#include <QLayout>

class DirectSlider : public QSlider
{
public:
    DirectSlider( QWidget *_parent ) : QSlider( _parent ) {};
    DirectSlider( Qt::Orientation q,QWidget *_parent ) : QSlider( q,_parent )
    {};
    virtual ~DirectSlider()   {};

    void mousePressEvent(QMouseEvent* event)
    {
        if(event->button() == Qt::LeftButton)
        {
#ifdef WIN32
            int width1 = qobject_cast<QWidget*>(parent())->sizeHint().width() -
                     2 * qobject_cast<QWidget*>(parent())->layout()->margin();
#else
            int width1 = width();
#endif
            int pos = (int)(minimum() +
                          (double)(event->x())/width1*(maximum()-minimum()) );
            setValue( pos );
            QSlider::mousePressEvent(event);
        }
    }
};
#endif
<commit_msg>Fix duration slider. Patch by Hannes Domani<commit_after>/*****************************************************************************
 * directslider.hpp : A slider that goes where you click
 ****************************************************************************
 * Copyright (C) 2006 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          with precious help from ahigerd on #qt@freenode
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/

#ifndef _DIRECTSLIDER_H_
#define _DIRECTSLIDER_H_

#include <QSlider>
#include <QMouseEvent>
#include <QLayout>

class DirectSlider : public QSlider
{
public:
    DirectSlider( QWidget *_parent ) : QSlider( _parent ) {};
    DirectSlider( Qt::Orientation q,QWidget *_parent ) : QSlider( q,_parent )
    {};
    virtual ~DirectSlider()   {};

    void mousePressEvent(QMouseEvent* event)
    {
        if( event->button() != Qt::LeftButton && event->button() != Qt::MidButton )
        {
            QSlider::mousePressEvent( event );
            return;
        }

        QMouseEvent newEvent( event->type(), event->pos(), event->globalPos(),
                Qt::MouseButton( event->button() ^ Qt::LeftButton ^ Qt::MidButton ),
                Qt::MouseButtons( event->buttons() ^ Qt::LeftButton ^ Qt::MidButton ),
                event->modifiers() );
        QSlider::mousePressEvent( &newEvent );
    }
};
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/system_monitor/system_monitor.h"
#include "base/values.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_browser_process_test.h"
#include "chrome/test/testing_pref_service.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {
// This global variable is used to check that value returned to different
// observers is the same.
Profile* g_created_profile;

}  // namespace

class ProfileManagerTest : public TestingBrowserProcessTest {
 protected:
  ProfileManagerTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        file_thread_(BrowserThread::FILE, &message_loop_),
        profile_manager_(new ProfileManagerWithoutInit),
        local_state_(testing_browser_process_.get()) {
#if defined(OS_MACOSX)
    base::SystemMonitor::AllocateSystemIOPorts();
#endif
    system_monitor_dummy_.reset(new base::SystemMonitor);
  }

  virtual void SetUp() {
    // Create a new temporary directory, and store the path
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  }

  virtual void TearDown() {
    profile_manager_.reset();
  }

  class MockObserver : public ProfileManagerObserver {
   public:
    MOCK_METHOD1(OnProfileCreated, void(Profile* profile));
  };

  // The path to temporary directory used to contain the test operations.
  ScopedTempDir temp_dir_;

  MessageLoopForUI message_loop_;
  BrowserThread ui_thread_;
  BrowserThread file_thread_;

  scoped_ptr<base::SystemMonitor> system_monitor_dummy_;

  // Also will test profile deletion.
  scoped_ptr<ProfileManager> profile_manager_;

  ScopedTestingLocalState local_state_;
};

TEST_F(ProfileManagerTest, GetProfile) {
  FilePath dest_path = temp_dir_.path();
  dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile"));

  Profile* profile;

  // Successfully create a profile.
  profile = profile_manager_->GetProfile(dest_path);
  EXPECT_TRUE(profile);

  // The profile already exists when we call GetProfile. Just load it.
  EXPECT_EQ(profile, profile_manager_->GetProfile(dest_path));
}

TEST_F(ProfileManagerTest, DefaultProfileDir) {
  CommandLine *cl = CommandLine::ForCurrentProcess();
  std::string profile_dir("my_user");

  cl->AppendSwitch(switches::kTestType);

  FilePath expected_default =
      FilePath().AppendASCII(chrome::kNotSignedInProfile);
  EXPECT_EQ(expected_default.value(),
            profile_manager_->GetCurrentProfileDir().value());
}

#if defined(OS_CHROMEOS)
// This functionality only exists on Chrome OS.
TEST_F(ProfileManagerTest, LoggedInProfileDir) {
  CommandLine *cl = CommandLine::ForCurrentProcess();
  std::string profile_dir("my_user");

  cl->AppendSwitchASCII(switches::kLoginProfile, profile_dir);
  cl->AppendSwitch(switches::kTestType);

  FilePath expected_default =
      FilePath().AppendASCII(chrome::kNotSignedInProfile);
  EXPECT_EQ(expected_default.value(),
            profile_manager_->GetCurrentProfileDir().value());

  profile_manager_->Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
                           NotificationService::AllSources(),
                           NotificationService::NoDetails());
  FilePath expected_logged_in(profile_dir);
  EXPECT_EQ(expected_logged_in.value(),
            profile_manager_->GetCurrentProfileDir().value());
  VLOG(1) << temp_dir_.path().Append(
      profile_manager_->GetCurrentProfileDir()).value();
}

#endif

TEST_F(ProfileManagerTest, RegisterProfileName) {
  // Create a test profile.
  FilePath dest_path1 = temp_dir_.path();
  std::string dir_base("New Profile 1");
  dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1"));
  Profile* profile1;
  profile1 = profile_manager_->GetProfile(dest_path1);
  ASSERT_TRUE(profile1);

  // Simulate registration of the profile name (normally triggered by the
  // change of the kGoogleServicesUsername preference):
  std::string testname("testname");
  profile1->GetPrefs()->SetString(prefs::kGoogleServicesUsername, testname);
  profile_manager_->RegisterProfileName(profile1);

  // Profile name should be associated with the directory in Local State.
  std::string stored_profile_name;
  const DictionaryValue* path_map = static_cast<const DictionaryValue*>(
      local_state_.Get()->GetUserPref(prefs::kProfileDirectoryMap));
  path_map->GetString(dir_base, &stored_profile_name);
  ASSERT_STREQ(testname.c_str(), stored_profile_name.c_str());
}

TEST_F(ProfileManagerTest, CreateAndUseTwoProfiles) {
  FilePath dest_path1 = temp_dir_.path();
  dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1"));

  FilePath dest_path2 = temp_dir_.path();
  dest_path2 = dest_path2.Append(FILE_PATH_LITERAL("New Profile 2"));

  Profile* profile1;
  Profile* profile2;

  // Successfully create the profiles.
  profile1 = profile_manager_->GetProfile(dest_path1);
  ASSERT_TRUE(profile1);

  profile2 = profile_manager_->GetProfile(dest_path2);
  ASSERT_TRUE(profile2);

  // Force lazy-init of some profile services to simulate use.
  EXPECT_TRUE(profile1->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_TRUE(profile1->GetBookmarkModel());
  EXPECT_TRUE(profile2->GetBookmarkModel());
  EXPECT_TRUE(profile2->GetHistoryService(Profile::EXPLICIT_ACCESS));

  // Make sure any pending tasks run before we destroy the profiles.
  message_loop_.RunAllPending();

  profile_manager_.reset();

  // Make sure history cleans up correctly.
  message_loop_.RunAllPending();
}

// Tests asynchronous profile creation mechanism.
TEST_F(ProfileManagerTest, CreateProfileAsync) {
  FilePath dest_path =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile"));

  MockObserver mock_observer;
  EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())).Times(1);

  profile_manager_->CreateProfileAsync(dest_path, &mock_observer);

  message_loop_.RunAllPending();
}

MATCHER(SameNotNull, "The same non-NULL value for all cals.") {
  if (!g_created_profile)
    g_created_profile = arg;
  return g_created_profile == arg;
}

TEST_F(ProfileManagerTest, CreateProfileAsyncMultipleRequests) {
  FilePath dest_path =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile"));

  g_created_profile = NULL;

  MockObserver mock_observer1;
  EXPECT_CALL(mock_observer1, OnProfileCreated(SameNotNull())).Times(1);
  MockObserver mock_observer2;
  EXPECT_CALL(mock_observer2, OnProfileCreated(SameNotNull())).Times(1);
  MockObserver mock_observer3;
  EXPECT_CALL(mock_observer3, OnProfileCreated(SameNotNull())).Times(1);

  profile_manager_->CreateProfileAsync(dest_path, &mock_observer1);
  profile_manager_->CreateProfileAsync(dest_path, &mock_observer2);
  profile_manager_->CreateProfileAsync(dest_path, &mock_observer3);

  message_loop_.RunAllPending();
}

TEST_F(ProfileManagerTest, CreateProfilesAsync) {
  FilePath dest_path1 =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile 1"));
  FilePath dest_path2 =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile 2"));

  MockObserver mock_observer;
  EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())).Times(2);

  profile_manager_->CreateProfileAsync(dest_path1, &mock_observer);
  profile_manager_->CreateProfileAsync(dest_path2, &mock_observer);

  message_loop_.RunAllPending();
}
<commit_msg>Disable ProfileManagerTest.CreateProfilesAsync due to crashes.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/scoped_temp_dir.h"
#include "base/system_monitor/system_monitor.h"
#include "base/values.h"
#include "chrome/browser/prefs/browser_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_browser_process_test.h"
#include "chrome/test/testing_pref_service.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {
// This global variable is used to check that value returned to different
// observers is the same.
Profile* g_created_profile;

}  // namespace

class ProfileManagerTest : public TestingBrowserProcessTest {
 protected:
  ProfileManagerTest()
      : ui_thread_(BrowserThread::UI, &message_loop_),
        file_thread_(BrowserThread::FILE, &message_loop_),
        profile_manager_(new ProfileManagerWithoutInit),
        local_state_(testing_browser_process_.get()) {
#if defined(OS_MACOSX)
    base::SystemMonitor::AllocateSystemIOPorts();
#endif
    system_monitor_dummy_.reset(new base::SystemMonitor);
  }

  virtual void SetUp() {
    // Create a new temporary directory, and store the path
    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  }

  virtual void TearDown() {
    profile_manager_.reset();
  }

  class MockObserver : public ProfileManagerObserver {
   public:
    MOCK_METHOD1(OnProfileCreated, void(Profile* profile));
  };

  // The path to temporary directory used to contain the test operations.
  ScopedTempDir temp_dir_;

  MessageLoopForUI message_loop_;
  BrowserThread ui_thread_;
  BrowserThread file_thread_;

  scoped_ptr<base::SystemMonitor> system_monitor_dummy_;

  // Also will test profile deletion.
  scoped_ptr<ProfileManager> profile_manager_;

  ScopedTestingLocalState local_state_;
};

TEST_F(ProfileManagerTest, GetProfile) {
  FilePath dest_path = temp_dir_.path();
  dest_path = dest_path.Append(FILE_PATH_LITERAL("New Profile"));

  Profile* profile;

  // Successfully create a profile.
  profile = profile_manager_->GetProfile(dest_path);
  EXPECT_TRUE(profile);

  // The profile already exists when we call GetProfile. Just load it.
  EXPECT_EQ(profile, profile_manager_->GetProfile(dest_path));
}

TEST_F(ProfileManagerTest, DefaultProfileDir) {
  CommandLine *cl = CommandLine::ForCurrentProcess();
  std::string profile_dir("my_user");

  cl->AppendSwitch(switches::kTestType);

  FilePath expected_default =
      FilePath().AppendASCII(chrome::kNotSignedInProfile);
  EXPECT_EQ(expected_default.value(),
            profile_manager_->GetCurrentProfileDir().value());
}

#if defined(OS_CHROMEOS)
// This functionality only exists on Chrome OS.
TEST_F(ProfileManagerTest, LoggedInProfileDir) {
  CommandLine *cl = CommandLine::ForCurrentProcess();
  std::string profile_dir("my_user");

  cl->AppendSwitchASCII(switches::kLoginProfile, profile_dir);
  cl->AppendSwitch(switches::kTestType);

  FilePath expected_default =
      FilePath().AppendASCII(chrome::kNotSignedInProfile);
  EXPECT_EQ(expected_default.value(),
            profile_manager_->GetCurrentProfileDir().value());

  profile_manager_->Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
                           NotificationService::AllSources(),
                           NotificationService::NoDetails());
  FilePath expected_logged_in(profile_dir);
  EXPECT_EQ(expected_logged_in.value(),
            profile_manager_->GetCurrentProfileDir().value());
  VLOG(1) << temp_dir_.path().Append(
      profile_manager_->GetCurrentProfileDir()).value();
}

#endif

TEST_F(ProfileManagerTest, RegisterProfileName) {
  // Create a test profile.
  FilePath dest_path1 = temp_dir_.path();
  std::string dir_base("New Profile 1");
  dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1"));
  Profile* profile1;
  profile1 = profile_manager_->GetProfile(dest_path1);
  ASSERT_TRUE(profile1);

  // Simulate registration of the profile name (normally triggered by the
  // change of the kGoogleServicesUsername preference):
  std::string testname("testname");
  profile1->GetPrefs()->SetString(prefs::kGoogleServicesUsername, testname);
  profile_manager_->RegisterProfileName(profile1);

  // Profile name should be associated with the directory in Local State.
  std::string stored_profile_name;
  const DictionaryValue* path_map = static_cast<const DictionaryValue*>(
      local_state_.Get()->GetUserPref(prefs::kProfileDirectoryMap));
  path_map->GetString(dir_base, &stored_profile_name);
  ASSERT_STREQ(testname.c_str(), stored_profile_name.c_str());
}

TEST_F(ProfileManagerTest, CreateAndUseTwoProfiles) {
  FilePath dest_path1 = temp_dir_.path();
  dest_path1 = dest_path1.Append(FILE_PATH_LITERAL("New Profile 1"));

  FilePath dest_path2 = temp_dir_.path();
  dest_path2 = dest_path2.Append(FILE_PATH_LITERAL("New Profile 2"));

  Profile* profile1;
  Profile* profile2;

  // Successfully create the profiles.
  profile1 = profile_manager_->GetProfile(dest_path1);
  ASSERT_TRUE(profile1);

  profile2 = profile_manager_->GetProfile(dest_path2);
  ASSERT_TRUE(profile2);

  // Force lazy-init of some profile services to simulate use.
  EXPECT_TRUE(profile1->GetHistoryService(Profile::EXPLICIT_ACCESS));
  EXPECT_TRUE(profile1->GetBookmarkModel());
  EXPECT_TRUE(profile2->GetBookmarkModel());
  EXPECT_TRUE(profile2->GetHistoryService(Profile::EXPLICIT_ACCESS));

  // Make sure any pending tasks run before we destroy the profiles.
  message_loop_.RunAllPending();

  profile_manager_.reset();

  // Make sure history cleans up correctly.
  message_loop_.RunAllPending();
}

// Tests asynchronous profile creation mechanism.
TEST_F(ProfileManagerTest, DISABLED_CreateProfileAsync) {
  FilePath dest_path =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile"));

  MockObserver mock_observer;
  EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())).Times(1);

  profile_manager_->CreateProfileAsync(dest_path, &mock_observer);

  message_loop_.RunAllPending();
}

MATCHER(SameNotNull, "The same non-NULL value for all cals.") {
  if (!g_created_profile)
    g_created_profile = arg;
  return g_created_profile == arg;
}

TEST_F(ProfileManagerTest, CreateProfileAsyncMultipleRequests) {
  FilePath dest_path =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile"));

  g_created_profile = NULL;

  MockObserver mock_observer1;
  EXPECT_CALL(mock_observer1, OnProfileCreated(SameNotNull())).Times(1);
  MockObserver mock_observer2;
  EXPECT_CALL(mock_observer2, OnProfileCreated(SameNotNull())).Times(1);
  MockObserver mock_observer3;
  EXPECT_CALL(mock_observer3, OnProfileCreated(SameNotNull())).Times(1);

  profile_manager_->CreateProfileAsync(dest_path, &mock_observer1);
  profile_manager_->CreateProfileAsync(dest_path, &mock_observer2);
  profile_manager_->CreateProfileAsync(dest_path, &mock_observer3);

  message_loop_.RunAllPending();
}

TEST_F(ProfileManagerTest, CreateProfilesAsync) {
  FilePath dest_path1 =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile 1"));
  FilePath dest_path2 =
      temp_dir_.path().Append(FILE_PATH_LITERAL("New Profile 2"));

  MockObserver mock_observer;
  EXPECT_CALL(mock_observer, OnProfileCreated(testing::NotNull())).Times(2);

  profile_manager_->CreateProfileAsync(dest_path1, &mock_observer);
  profile_manager_->CreateProfileAsync(dest_path2, &mock_observer);

  message_loop_.RunAllPending();
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/speech/speech_recognition_request.h"

#include "base/json/json_reader.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_status.h"

namespace {

// TODO(satish): Change this once speex compression is enabled for audio.
const char kMimeRawAudio[] = "audio/l16; rate=8000";

const char* const kHypothesesString = "hypotheses";
const char* const kUtteranceString = "utterance";

bool ParseServerResponse(const std::string& response_body, string16* value) {
  DCHECK(value);

  if (response_body.empty()) {
    LOG(WARNING) << "ParseServerResponse: Response was empty.\n";
    return false;
  }
  DLOG(INFO) << "ParseServerResponse: Parsing response "
             << response_body << ".\n";

  // Parse the response, ignoring comments.
  std::string error_msg;
  scoped_ptr<Value> response_value(base::JSONReader::ReadAndReturnError(
      response_body, false, NULL, &error_msg));
  if (response_value == NULL) {
    LOG(WARNING) << "ParseServerResponse: JSONReader failed : "
                 << error_msg << ".\n";
    return false;
  }

  if (!response_value->IsType(Value::TYPE_DICTIONARY)) {
    LOG(INFO) << "ParseServerResponse: Unexpected response type "
              << response_value->GetType() <<  ".\n";
    return false;
  }
  const DictionaryValue* response_object =
      static_cast<DictionaryValue*>(response_value.get());

  // Get the hypotheses
  Value* hypotheses_value = NULL;
  if (!response_object->Get(kHypothesesString, &hypotheses_value)) {
    LOG(INFO) << "ParseServerResponse: Missing hypotheses attribute.\n";
    return false;
  }
  DCHECK(hypotheses_value);
  if (!hypotheses_value->IsType(Value::TYPE_LIST)) {
    LOG(INFO) << "ParseServerResponse: Unexpected hypotheses type "
              << hypotheses_value->GetType() <<  ".\n";
    return false;
  }
  const ListValue* hypotheses_list = static_cast<ListValue*>(hypotheses_value);
  if (hypotheses_list->GetSize() == 0) {
    LOG(INFO) << "ParseServerResponse: hypotheses list is empty.\n";
    return false;
  }

  Value* first_hypotheses = NULL;
  if (!hypotheses_list->Get(0, &first_hypotheses)) {
    LOG(INFO) << "ParseServerResponse: Unable to read hypotheses value.\n";
    return false;
  }
  DCHECK(first_hypotheses);
  if (!first_hypotheses->IsType(Value::TYPE_DICTIONARY)) {
    LOG(INFO) << "ParseServerResponse: Unexpected value type "
              << first_hypotheses->GetType() <<  ".\n";
    return false;
  }
  const DictionaryValue* first_hypotheses_value =
      static_cast<DictionaryValue*>(first_hypotheses);
  if (!first_hypotheses_value->GetString(kUtteranceString, value)) {
    LOG(INFO) << "ParseServerResponse: Missing utterance value.\n";
    return false;
  }

  return true;
}

}  // namespace

namespace speech_input {

int SpeechRecognitionRequest::url_fetcher_id_for_tests = 0;

SpeechRecognitionRequest::SpeechRecognitionRequest(
    URLRequestContextGetter* context, const GURL& url, Delegate* delegate)
    : url_context_(context),
      url_(url),
      delegate_(delegate) {
  DCHECK(delegate);
}

bool SpeechRecognitionRequest::Send(const std::string& audio_data) {
  DCHECK(!url_fetcher_.get());

  url_fetcher_.reset(URLFetcher::Create(
      url_fetcher_id_for_tests, url_, URLFetcher::POST, this));
  url_fetcher_->set_upload_data(kMimeRawAudio, audio_data);
  url_fetcher_->set_request_context(url_context_);
  url_fetcher_->set_load_flags(
      net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
      net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES |
      net::LOAD_DO_NOT_SEND_AUTH_DATA);
  url_fetcher_->Start();
  return true;
}

void SpeechRecognitionRequest::OnURLFetchComplete(
    const URLFetcher* source,
    const GURL& url,
    const URLRequestStatus& status,
    int response_code,
    const ResponseCookies& cookies,
    const std::string& data) {
  DCHECK_EQ(url_fetcher_.get(), source);
  DCHECK(url_.possibly_invalid_spec() == url.possibly_invalid_spec());

  bool error = !status.is_success() || response_code != 200;
  string16 value;
  if (!error)
    error = !ParseServerResponse(data, &value);
  url_fetcher_.reset();

  DLOG(INFO) << "SpeechRecognitionRequest: Invoking delegate with result.";
  delegate_->SetRecognitionResult(error, value);
}

}  // namespace speech_input
<commit_msg>Address Andrei's comments from CL 3164002 TEST=none BUG=none<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/speech/speech_recognition_request.h"

#include "base/json/json_reader.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_status.h"

namespace {

// TODO(satish): Change this once speex compression is enabled for audio.
const char kMimeRawAudio[] = "audio/l16; rate=8000";

const char* const kHypothesesString = "hypotheses";
const char* const kUtteranceString = "utterance";

bool ParseServerResponse(const std::string& response_body, string16* value) {
  DCHECK(value);

  if (response_body.empty()) {
    LOG(WARNING) << "ParseServerResponse: Response was empty.\n";
    return false;
  }
  DLOG(INFO) << "ParseServerResponse: Parsing response "
             << response_body << ".\n";

  // Parse the response, ignoring comments.
  std::string error_msg;
  scoped_ptr<Value> response_value(base::JSONReader::ReadAndReturnError(
      response_body, false, NULL, &error_msg));
  if (response_value == NULL) {
    LOG(WARNING) << "ParseServerResponse: JSONReader failed : "
                 << error_msg << ".\n";
    return false;
  }

  if (!response_value->IsType(Value::TYPE_DICTIONARY)) {
    LOG(INFO) << "ParseServerResponse: Unexpected response type "
              << response_value->GetType() <<  ".\n";
    return false;
  }
  const DictionaryValue* response_object =
      static_cast<DictionaryValue*>(response_value.get());

  // Get the hypotheses
  Value* hypotheses_value = NULL;
  if (!response_object->Get(kHypothesesString, &hypotheses_value)) {
    LOG(INFO) << "ParseServerResponse: Missing hypotheses attribute.\n";
    return false;
  }
  DCHECK(hypotheses_value);
  if (!hypotheses_value->IsType(Value::TYPE_LIST)) {
    LOG(INFO) << "ParseServerResponse: Unexpected hypotheses type "
              << hypotheses_value->GetType() <<  ".\n";
    return false;
  }
  const ListValue* hypotheses_list = static_cast<ListValue*>(hypotheses_value);
  if (hypotheses_list->GetSize() == 0) {
    LOG(INFO) << "ParseServerResponse: hypotheses list is empty.\n";
    return false;
  }

  Value* first_hypotheses = NULL;
  if (!hypotheses_list->Get(0, &first_hypotheses)) {
    LOG(INFO) << "ParseServerResponse: Unable to read hypotheses value.\n";
    return false;
  }
  DCHECK(first_hypotheses);
  if (!first_hypotheses->IsType(Value::TYPE_DICTIONARY)) {
    LOG(INFO) << "ParseServerResponse: Unexpected value type "
              << first_hypotheses->GetType() <<  ".\n";
    return false;
  }
  const DictionaryValue* first_hypotheses_value =
      static_cast<DictionaryValue*>(first_hypotheses);
  if (!first_hypotheses_value->GetString(kUtteranceString, value)) {
    LOG(INFO) << "ParseServerResponse: Missing utterance value.\n";
    return false;
  }

  return true;
}

}  // namespace

namespace speech_input {

int SpeechRecognitionRequest::url_fetcher_id_for_tests = 0;

SpeechRecognitionRequest::SpeechRecognitionRequest(
    URLRequestContextGetter* context, const GURL& url, Delegate* delegate)
    : url_context_(context),
      url_(url),
      delegate_(delegate) {
  DCHECK(delegate);
}

bool SpeechRecognitionRequest::Send(const std::string& audio_data) {
  DCHECK(!url_fetcher_.get());

  url_fetcher_.reset(URLFetcher::Create(
      url_fetcher_id_for_tests, url_, URLFetcher::POST, this));
  url_fetcher_->set_upload_data(kMimeRawAudio, audio_data);
  url_fetcher_->set_request_context(url_context_);

  // The speech recognition API does not require user identification as part
  // of requests, so we don't send cookies or auth data for these requests to
  // prevent any accidental connection between users who are logged into the
  // domain for other services (e.g. bookmark sync) with the speech requests.
  url_fetcher_->set_load_flags(
      net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES |
      net::LOAD_DO_NOT_SEND_AUTH_DATA);
  url_fetcher_->Start();
  return true;
}

void SpeechRecognitionRequest::OnURLFetchComplete(
    const URLFetcher* source,
    const GURL& url,
    const URLRequestStatus& status,
    int response_code,
    const ResponseCookies& cookies,
    const std::string& data) {
  DCHECK_EQ(url_fetcher_.get(), source);
  DCHECK(url_.possibly_invalid_spec() == url.possibly_invalid_spec());

  bool error = !status.is_success() || response_code != 200;
  string16 value;
  if (!error)
    error = !ParseServerResponse(data, &value);
  url_fetcher_.reset();

  DLOG(INFO) << "SpeechRecognitionRequest: Invoking delegate with result.";
  delegate_->SetRecognitionResult(error, value);
}

}  // namespace speech_input
<|endoftext|>