### Issue Details

* **Electron Version:**
  * 12, 11, 10, 9
* **Operating System:**
  * all
* **Last Known Working Electron version:**
  * NA

### Expected Behavior
The Promise returned by `contentTracing.stopTracing()` should always either resolve or reject.

### Actual Behavior
If called when a trace is not in progress, `contentTracing.stopTracing()` never resolves or rejects.

### To Reproduce
https://gist.github.com/8eb40af81ba15dbe4c50735a6ec4489d

note `'done'` is never printed.
shell/browser/api/electron_api_content_tracing.cc
base::Optional<base::FilePath> file_path) {
  if (file_path) {
    auto endpoint = TracingController::CreateFileEndpoint(
        *file_path, base::AdaptCallbackForRepeating(base::BindOnce(
                        &gin_helper::Promise<base::FilePath>::ResolvePromise,
                        std::move(promise), *file_path)));
    TracingController::GetInstance()->StopTracing(endpoint);
  } else {
    promise.RejectWithErrorMessage(
        "Failed to create temporary file for trace data");
  }
}
v8::Local<v8::Promise> StopRecording(gin_helper::Arguments* args) {
  gin_helper::Promise<base::FilePath> promise(args->isolate());
  v8::Local<v8::Promise> handle = promise.GetHandle();
  base::FilePath path;
  if (args->GetNext(&path) && !path.empty()) {
    StopTracing(std::move(promise), base::make_optional(path));
  } else {
    
    base::ThreadPool::PostTaskAndReplyWithResult(
        FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
        base::BindOnce(CreateTemporaryFileOnIO),
        base::BindOnce(StopTracing, std::move(promise)));
  }
  return handle;
}
v8::Local<v8::Promise> GetCategories(v8::Isolate* isolate) {