// Copyright (c) 2018 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/media/router/discovery/dial/dial_url_fetcher.h"

#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"

// The maximum number of retries allowed for GET requests.
constexpr int kMaxRetries = 2;

// DIAL devices are unlikely to expose uPnP functions other than DIAL, so 256kb
// should be more than sufficient.
constexpr int kMaxResponseSizeBytes = 262144;

namespace media_router {

namespace {

constexpr net::NetworkTrafficAnnotationTag kDialUrlFetcherTrafficAnnotation =
    net::DefineNetworkTrafficAnnotation("dial_url_fetcher", R"(
        semantics {
          sender: "DIAL"
          description:
            "Chromium sends a request to a device (such as a smart TV) "
            "discovered via the DIAL (Discovery and Launch) protocol to obtain "
            "its device description or app info data. Chromium then uses the "
            "data to determine the capabilities of the device to be used as a "
            "targetfor casting media content."
          trigger:
            "A new or updated device has been discovered via DIAL in the local "
            "network."
          data: "An HTTP GET request."
          destination: OTHER
          destination_other:
            "A device in the local network."
        }
        policy {
          cookies_allowed: NO
          setting:
            "This feature cannot be disabled by settings."
          chrome_policy {
            EnableMediaRouter {
              policy_options {mode: MANDATORY}
              EnableMediaRouter: false
            }
          }
        })");

void BindURLLoaderFactoryRequestOnUIThread(
    network::mojom::URLLoaderFactoryRequest request) {
  network::mojom::URLLoaderFactory* factory =
      g_browser_process->system_network_context_manager()
          ->GetURLLoaderFactory();
  factory->Clone(std::move(request));
}

}  // namespace

DialURLFetcher::DialURLFetcher(DialURLFetcher::SuccessCallback success_cb,
                               DialURLFetcher::ErrorCallback error_cb)
    : success_cb_(std::move(success_cb)), error_cb_(std::move(error_cb)) {}

DialURLFetcher::~DialURLFetcher() {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}

const network::ResourceResponseHead* DialURLFetcher::GetResponseHead() const {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  return loader_ ? loader_->ResponseInfo() : nullptr;
}

void DialURLFetcher::Get(const GURL& url) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  Start(url, "GET", base::nullopt, kMaxRetries);
}

void DialURLFetcher::Delete(const GURL& url) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  Start(url, "DELETE", base::nullopt, 0);
}

void DialURLFetcher::Post(const GURL& url,
                          const base::Optional<std::string>& post_data) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  Start(url, "POST", post_data, 0);
}

void DialURLFetcher::Start(const GURL& url,
                           const std::string& method,
                           const base::Optional<std::string>& post_data,
                           int max_retries) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  DCHECK(!loader_);

  auto request = std::make_unique<network::ResourceRequest>();
  request->url = url;
  request->method = method;
  method_ = method;

  // net::LOAD_BYPASS_PROXY: Proxies almost certainly hurt more cases than they
  //     help.
  // net::LOAD_DISABLE_CACHE: The request should not touch the cache.
  // net::LOAD_DO_NOT_{SAVE,SEND}_COOKIES: The request should not touch cookies.
  // net::LOAD_DO_NOT_SEND_AUTH_DATA: The request should not send auth data.
  request->load_flags = net::LOAD_BYPASS_PROXY | net::LOAD_DISABLE_CACHE |
                        net::LOAD_DO_NOT_SAVE_COOKIES |
                        net::LOAD_DO_NOT_SEND_COOKIES |
                        net::LOAD_DO_NOT_SEND_AUTH_DATA;

  loader_ = network::SimpleURLLoader::Create(std::move(request),
                                             kDialUrlFetcherTrafficAnnotation);

  // Allow the fetcher to retry on 5XX responses and ERR_NETWORK_CHANGED.
  if (max_retries > 0) {
    loader_->SetRetryOptions(
        max_retries,
        network::SimpleURLLoader::RetryMode::RETRY_ON_5XX |
            network::SimpleURLLoader::RetryMode::RETRY_ON_NETWORK_CHANGE);
  }

  // Section 5.4 of the DIAL spec prohibits redirects.
  // In practice, the callback will only get called once, since |loader_| will
  // be deleted.
  loader_->SetOnRedirectCallback(base::BindRepeating(
      &DialURLFetcher::ReportRedirectError, base::Unretained(this)));

  if (post_data)
    loader_->AttachStringForUpload(*post_data, "text/plain");

  StartDownload();
}

void DialURLFetcher::ReportError(int response_code,
                                 const std::string& message) {
  std::move(error_cb_).Run(response_code, message);
}

void DialURLFetcher::ReportRedirectError(
    const net::RedirectInfo& redirect_info,
    const network::ResourceResponseHead& response_head,
    std::vector<std::string>* to_be_removed_headers) {
  // Cancel the request.
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  loader_.reset();

  // Returning |OK| on error will be treated as unavailable.
  ReportError(net::Error::OK, "Redirect not allowed");
}

void DialURLFetcher::StartDownload() {
  // Bind the request to the system URLLoaderFactory obtained on UI thread.
  // Currently this is the only way to guarantee a live URLLoaderFactory.
  // TOOD(mmenke): Figure out a way to do this transparently on IO thread.
  network::mojom::URLLoaderFactoryPtr loader_factory;

  // TODO(https://crbug.com/823869): Fix DeviceDescriptionServiceTest and remove
  // this conditional.
  auto mojo_request = mojo::MakeRequest(&loader_factory);
  if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI)) {
    content::BrowserThread::PostTask(
        content::BrowserThread::UI, FROM_HERE,
        base::BindOnce(&BindURLLoaderFactoryRequestOnUIThread,
                       std::move(mojo_request)));
  }

  loader_->DownloadToString(
      loader_factory.get(),
      base::BindOnce(&DialURLFetcher::ProcessResponse, base::Unretained(this)),
      kMaxResponseSizeBytes);
}

void DialURLFetcher::ProcessResponse(std::unique_ptr<std::string> response) {
  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  int response_code = loader_->NetError();
  if (response_code != net::Error::OK) {
    ReportError(response_code,
                base::StringPrintf("HTTP response error: %d", response_code));
    return;
  }

  // Response for POST and DELETE may be empty.
  if (!response || (method_ == "GET" && response->empty())) {
    ReportError(response_code, "Missing or empty response");
    return;
  }

  if (!base::IsStringUTF8(*response)) {
    ReportError(response_code, "Invalid response encoding");
    return;
  }

  std::move(success_cb_).Run(*response);
}

}  // namespace media_router
