text: // Copyright 2020 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 "media/fuchsia/cdm/service/provisioning_fetcher_impl.h"
  
  #include "base/bind.h"
  #include "base/callback.h"
  #include "base/fuchsia/fuchsia_logging.h"
  #include "base/logging.h"
  #include "fuchsia/base/mem_buffer_util.h"
  
  namespace media {
  
  ProvisioningFetcherImpl::ProvisioningFetcherImpl(
      CreateFetcherCB create_fetcher_callback)
      : create_fetcher_callback_(std::move(create_fetcher_callback)),
        binding_(this) {
    DCHECK(create_fetcher_callback_);
  }
  
  ProvisioningFetcherImpl::~ProvisioningFetcherImpl() = default;
  
  fidl::InterfaceHandle<fuchsia::media::drm::ProvisioningFetcher>
  ProvisioningFetcherImpl::Bind(base::OnceClosure error_callback) {
    error_callback_ = std::move(error_callback);
  
    binding_.set_error_handler(
        [&error_callback = error_callback_](zx_status_t status) {
          ZX_DLOG_IF(ERROR, (status != ZX_OK) && (status != ZX_ERR_PEER_CLOSED),
                     status)
              << "ProvisioningFetcher closed with an unexpected status";
          std::move(error_callback).Run();
        });
    return binding_.NewBinding();
  }
  
  void ProvisioningFetcherImpl::Fetch(
      fuchsia::media::drm::ProvisioningRequest request,
      FetchCallback callback) {
    if (retrieve_in_progress_) {
      DLOG(WARNING)
          << "ProvisioningFetcherImpl received too many ProvisioningRequests";
      OnError(ZX_ERR_BAD_STATE);
      return;
    }
  
    std::string request_str;
    if (!cr_fuchsia::StringFromMemBuffer(request.message, &request_str)) {
      DLOG(WARNING) << "Failed to read ProvisioningRequest.";
      OnError(ZX_ERR_INVALID_ARGS);
      return;
    }
  
    if (!request.default_provisioning_server_url) {
      DLOG(WARNING) << "Missing default provisioning server URL.";
      OnError(ZX_ERR_INVALID_ARGS);
      return;
    }
  
    if (!fetcher_) {
      fetcher_ = create_fetcher_callback_.Run();
    }
  
    retrieve_in_progress_ = true;
    fetcher_->Retrieve(
        GURL(request.default_provisioning_server_url.value()), request_str,
        base::BindRepeating(&ProvisioningFetcherImpl::OnRetrieveComplete,
                            base::Unretained(this),
                            base::Passed(std::move(callback))));
  }
  
  void ProvisioningFetcherImpl::OnRetrieveComplete(FetchCallback callback,
                                                   bool success,
                                                   const std::string& response) {
    retrieve_in_progress_ = false;
    // Regardless of success or failure, send the response back to acknowledge
    // it has been completed.
    DLOG_IF(WARNING, !success) << "Failed to fetch provision response.";
  
    fuchsia::media::drm::ProvisioningResponse provision_response;
    provision_response.message =
        cr_fuchsia::MemBufferFromString(response, "cr-drm-provision-response");
  
    callback(std::move(provision_response));
  }
  
  void ProvisioningFetcherImpl::OnError(zx_status_t status) {
    DCHECK(error_callback_);
  
    binding_.Close(status);
    std::move(error_callback_).Run();
  }
  
  }  // namespace media
  