// Copyright 2017 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 "content/browser/background_fetch/background_fetch_delegate_proxy.h"

#include <utility>

#include "base/task/post_task.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_url_parameters.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/public/browser/background_fetch_description.h"
#include "content/public/browser/background_fetch_response.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/download_manager.h"
#include "third_party/blink/public/mojom/blob/serialized_blob.mojom.h"
#include "ui/gfx/geometry/size.h"

class SkBitmap;

namespace content {

// Internal functionality of the BackgroundFetchDelegateProxy that lives on the
// UI thread, where all interaction with the download manager must happen.
class BackgroundFetchDelegateProxy::Core
    : public BackgroundFetchDelegate::Client {
 public:
  Core(const base::WeakPtr<BackgroundFetchDelegateProxy>& io_parent,
       BrowserContext* browser_context)
      : io_parent_(io_parent),
        browser_context_(browser_context),
        weak_ptr_factory_(this) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK(browser_context_);
  }

  ~Core() override { DCHECK_CURRENTLY_ON(BrowserThread::UI); }

  base::WeakPtr<Core> GetWeakPtrOnUI() {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    return weak_ptr_factory_.GetWeakPtr();
  }

  void ForwardGetPermissionForOriginCallbackToIO(
      BackgroundFetchDelegate::GetPermissionForOriginCallback callback,
      BackgroundFetchPermission permission) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
                             base::BindOnce(std::move(callback), permission));
  }

  void GetPermissionForOrigin(
      const url::Origin& origin,
      const ResourceRequestInfo::WebContentsGetter& wc_getter,
      BackgroundFetchDelegate::GetPermissionForOriginCallback callback) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    if (auto* delegate = browser_context_->GetBackgroundFetchDelegate()) {
      delegate->GetPermissionForOrigin(
          origin, wc_getter,
          base::BindOnce(&Core::ForwardGetPermissionForOriginCallbackToIO,
                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
    } else {
      std::move(callback).Run(BackgroundFetchPermission::BLOCKED);
    }
  }

  void ForwardGetIconDisplaySizeCallbackToIO(
      BackgroundFetchDelegate::GetIconDisplaySizeCallback callback,
      const gfx::Size& display_size) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
                             base::BindOnce(std::move(callback), display_size));
  }

  void GetIconDisplaySize(
      BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    if (auto* delegate = browser_context_->GetBackgroundFetchDelegate()) {
      delegate->GetIconDisplaySize(
          base::BindOnce(&Core::ForwardGetIconDisplaySizeCallbackToIO,
                         weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
    } else {
      base::PostTaskWithTraits(
          FROM_HERE, {BrowserThread::IO},
          base::BindOnce(std::move(callback), gfx::Size(0, 0)));
    }
  }

  void CreateDownloadJob(
      std::unique_ptr<BackgroundFetchDescription> fetch_description) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    auto* delegate = browser_context_->GetBackgroundFetchDelegate();
    if (delegate)
      delegate->CreateDownloadJob(GetWeakPtrOnUI(),
                                  std::move(fetch_description));
  }

  void StartRequest(const std::string& job_unique_id,
                    const url::Origin& origin,
                    scoped_refptr<BackgroundFetchRequestInfo> request) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    DCHECK(request);

    // TODO(crbug/757760): This can be nullptr, if the delegate has shut down,
    // in which case we need to make sure this is retried when the browser
    // restarts.
    auto* delegate = browser_context_->GetBackgroundFetchDelegate();
    if (!delegate)
      return;

    const blink::mojom::FetchAPIRequestPtr& fetch_request =
        request->fetch_request();

    const net::NetworkTrafficAnnotationTag traffic_annotation(
        net::DefineNetworkTrafficAnnotation("background_fetch_context",
                                            R"(
            semantics {
              sender: "Background Fetch API"
              description:
                "The Background Fetch API enables developers to upload or "
                "download files on behalf of the user. Such fetches will yield "
                "a user visible notification to inform the user of the "
                "operation, through which it can be suspended, resumed and/or "
                "cancelled. The developer retains control of the file once the "
                "fetch is completed,  similar to XMLHttpRequest and other "
                "mechanisms for fetching resources using JavaScript."
              trigger:
                "When the website uses the Background Fetch API to request "
                "fetching a file and/or a list of files. This is a Web "
                "Platform API for which no express user permission is required."
              data:
                "The request headers and data as set by the website's "
                "developer."
              destination: WEBSITE
            }
            policy {
              cookies_allowed: YES
              cookies_store: "user"
              setting: "This feature cannot be disabled in settings."
              policy_exception_justification: "Not implemented."
            })"));

    // TODO(peter): The |headers| should be populated with all the properties
    // set in the |fetch_request| structure.
    net::HttpRequestHeaders headers;
    for (const auto& pair : fetch_request->headers)
      headers.SetHeader(pair.first, pair.second);

    // Append the Origin header for requests whose CORS flag is set, or whose
    // request method is not GET or HEAD. See section 3.1 of the standard:
    // https://fetch.spec.whatwg.org/#origin-header
    if (fetch_request->mode == network::mojom::FetchRequestMode::kCors ||
        fetch_request->mode ==
            network::mojom::FetchRequestMode::kCorsWithForcedPreflight ||
        (fetch_request->method != "GET" && fetch_request->method != "HEAD")) {
      headers.SetHeader("Origin", origin.Serialize());
    }

    delegate->DownloadUrl(
        job_unique_id, request->download_guid(), fetch_request->method,
        fetch_request->url, traffic_annotation, headers,
        /* has_request_body= */ request->request_body_size() > 0u);
  }

  void Abort(const std::string& job_unique_id) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    if (auto* delegate = browser_context_->GetBackgroundFetchDelegate())
      delegate->Abort(job_unique_id);
  }

  void MarkJobComplete(const std::string& job_unique_id) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    if (auto* delegate = browser_context_->GetBackgroundFetchDelegate())
      delegate->MarkJobComplete(job_unique_id);
  }

  void UpdateUI(const std::string& job_unique_id,
                const base::Optional<std::string>& title,
                const base::Optional<SkBitmap>& icon) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);

    if (auto* delegate = browser_context_->GetBackgroundFetchDelegate())
      delegate->UpdateUI(job_unique_id, title, icon);
  }

  // BackgroundFetchDelegate::Client implementation:
  void OnJobCancelled(
      const std::string& job_unique_id,
      blink::mojom::BackgroundFetchFailureReason reason_to_abort) override;
  void OnDownloadUpdated(const std::string& job_unique_id,
                         const std::string& guid,
                         uint64_t bytes_uploaded,
                         uint64_t bytes_downloaded) override;
  void OnDownloadComplete(
      const std::string& job_unique_id,
      const std::string& guid,
      std::unique_ptr<BackgroundFetchResult> result) override;
  void OnDownloadStarted(
      const std::string& job_unique_id,
      const std::string& guid,
      std::unique_ptr<content::BackgroundFetchResponse> response) override;
  void OnUIActivated(const std::string& unique_id) override;
  void GetUploadData(
      const std::string& job_unique_id,
      const std::string& download_guid,
      BackgroundFetchDelegate::GetUploadDataCallback callback) override;

 private:
  // Weak reference to the IO thread outer class that owns us.
  base::WeakPtr<BackgroundFetchDelegateProxy> io_parent_;

  BrowserContext* browser_context_;

  base::WeakPtrFactory<Core> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(Core);
};

void BackgroundFetchDelegateProxy::Core::OnJobCancelled(
    const std::string& job_unique_id,
    blink::mojom::BackgroundFetchFailureReason reason_to_abort) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BackgroundFetchDelegateProxy::OnJobCancelled, io_parent_,
                     job_unique_id, reason_to_abort));
}

void BackgroundFetchDelegateProxy::Core::OnDownloadUpdated(
    const std::string& job_unique_id,
    const std::string& guid,
    uint64_t bytes_uploaded,
    uint64_t bytes_downloaded) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BackgroundFetchDelegateProxy::OnDownloadUpdated,
                     io_parent_, job_unique_id, guid, bytes_uploaded,
                     bytes_downloaded));
}

void BackgroundFetchDelegateProxy::Core::OnDownloadComplete(
    const std::string& job_unique_id,
    const std::string& guid,
    std::unique_ptr<BackgroundFetchResult> result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BackgroundFetchDelegateProxy::OnDownloadComplete,
                     io_parent_, job_unique_id, guid, std::move(result)));
}

void BackgroundFetchDelegateProxy::Core::OnDownloadStarted(
    const std::string& job_unique_id,
    const std::string& guid,
    std::unique_ptr<content::BackgroundFetchResponse> response) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BackgroundFetchDelegateProxy::DidStartRequest, io_parent_,
                     job_unique_id, guid, std::move(response)));
}

void BackgroundFetchDelegateProxy::Core::OnUIActivated(
    const std::string& job_unique_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BackgroundFetchDelegateProxy::DidActivateUI, io_parent_,
                     job_unique_id));
}

void BackgroundFetchDelegateProxy::Core::GetUploadData(
    const std::string& job_unique_id,
    const std::string& download_guid,
    BackgroundFetchDelegate::GetUploadDataCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Pass this to the IO thread for processing, but wrap |callback|
  // to be posted back to the UI thread when executed.
  BackgroundFetchDelegate::GetUploadDataCallback wrapped_callback =
      base::BindOnce(
          [](BackgroundFetchDelegate::GetUploadDataCallback callback,
             blink::mojom::SerializedBlobPtr blob) {
            base::PostTaskWithTraits(
                FROM_HERE, {BrowserThread::UI},
                base::BindOnce(std::move(callback), std::move(blob)));
          },
          std::move(callback));

  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::IO},
      base::BindOnce(&BackgroundFetchDelegateProxy::GetUploadData, io_parent_,
                     job_unique_id, download_guid,
                     std::move(wrapped_callback)));
}

BackgroundFetchDelegateProxy::JobDetails::JobDetails(
    base::WeakPtr<Controller> controller,
    std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
        active_fetch_requests)
    : controller(controller) {
  for (auto& request_info : active_fetch_requests) {
    DCHECK(request_info);
    std::string download_guid = request_info->download_guid();
    current_request_map[std::move(download_guid)] = std::move(request_info);
  }
}

BackgroundFetchDelegateProxy::JobDetails::JobDetails(JobDetails&& details) =
    default;

BackgroundFetchDelegateProxy::JobDetails::~JobDetails() = default;

BackgroundFetchDelegateProxy::BackgroundFetchDelegateProxy(
    BrowserContext* browser_context)
    : weak_ptr_factory_(this) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // Normally it would be unsafe to obtain a weak pointer on the UI thread from
  // a factory that lives on the IO thread, but it's ok in the constructor as
  // |this| can't be destroyed before the constructor finishes.
  ui_core_.reset(new Core(weak_ptr_factory_.GetWeakPtr(), browser_context));

  // Since this constructor runs on the UI thread, a WeakPtr can be safely
  // obtained from the Core.
  ui_core_ptr_ = ui_core_->GetWeakPtrOnUI();
}

BackgroundFetchDelegateProxy::~BackgroundFetchDelegateProxy() {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
}

void BackgroundFetchDelegateProxy::SetClickEventDispatcher(
    const DispatchClickEventCallback callback) {
  click_event_dispatcher_callback_ = std::move(callback);
}

void BackgroundFetchDelegateProxy::GetIconDisplaySize(
    BackgroundFetchDelegate::GetIconDisplaySizeCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
                           base::BindOnce(&Core::GetIconDisplaySize,
                                          ui_core_ptr_, std::move(callback)));
}

void BackgroundFetchDelegateProxy::GetPermissionForOrigin(
    const url::Origin& origin,
    const ResourceRequestInfo::WebContentsGetter& wc_getter,
    BackgroundFetchDelegate::GetPermissionForOriginCallback callback) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&Core::GetPermissionForOrigin, ui_core_ptr_, origin,
                     wc_getter, std::move(callback)));
}

void BackgroundFetchDelegateProxy::CreateDownloadJob(
    base::WeakPtr<Controller> controller,
    std::unique_ptr<BackgroundFetchDescription> fetch_description,
    std::vector<scoped_refptr<BackgroundFetchRequestInfo>>
        active_fetch_requests) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  DCHECK(!job_details_map_.count(fetch_description->job_unique_id));
  job_details_map_.emplace(
      fetch_description->job_unique_id,
      JobDetails(controller, std::move(active_fetch_requests)));

  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&Core::CreateDownloadJob, ui_core_ptr_,
                     std::move(fetch_description)));
}

void BackgroundFetchDelegateProxy::StartRequest(
    const std::string& job_unique_id,
    const url::Origin& origin,
    scoped_refptr<BackgroundFetchRequestInfo> request) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  DCHECK(job_details_map_.count(job_unique_id));
  JobDetails& job_details = job_details_map_.find(job_unique_id)->second;
  DCHECK(job_details.controller);

  std::string download_guid = request->download_guid();
  DCHECK(!download_guid.empty());

  job_details.current_request_map[download_guid] = request;

  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
                           base::BindOnce(&Core::StartRequest, ui_core_ptr_,
                                          job_unique_id, origin, request));
}

void BackgroundFetchDelegateProxy::UpdateUI(
    const std::string& job_unique_id,
    const base::Optional<std::string>& title,
    const base::Optional<SkBitmap>& icon) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
                           base::BindOnce(&Core::UpdateUI, ui_core_ptr_,
                                          job_unique_id, title, icon));
}

void BackgroundFetchDelegateProxy::Abort(const std::string& job_unique_id) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&Core::Abort, ui_core_ptr_, job_unique_id));
}

void BackgroundFetchDelegateProxy::MarkJobComplete(
    const std::string& job_unique_id) {
  base::PostTaskWithTraits(
      FROM_HERE, {BrowserThread::UI},
      base::BindOnce(&Core::MarkJobComplete, ui_core_ptr_, job_unique_id));
  job_details_map_.erase(job_unique_id);
}

void BackgroundFetchDelegateProxy::OnJobCancelled(
    const std::string& job_unique_id,
    blink::mojom::BackgroundFetchFailureReason reason_to_abort) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);
  DCHECK(
      reason_to_abort ==
          blink::mojom::BackgroundFetchFailureReason::CANCELLED_FROM_UI ||
      reason_to_abort ==
          blink::mojom::BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED);

  // TODO(delphick): The controller may not exist as persistence is not yet
  // implemented.
  auto job_details_iter = job_details_map_.find(job_unique_id);
  if (job_details_iter == job_details_map_.end())
    return;

  JobDetails& job_details = job_details_iter->second;
  if (job_details.controller)
    job_details.controller->AbortFromDelegate(reason_to_abort);
}

void BackgroundFetchDelegateProxy::DidStartRequest(
    const std::string& job_unique_id,
    const std::string& guid,
    std::unique_ptr<BackgroundFetchResponse> response) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // TODO(delphick): The controller may not exist as persistence is not yet
  // implemented.
  auto job_details_iter = job_details_map_.find(job_unique_id);
  if (job_details_iter == job_details_map_.end())
    return;

  JobDetails& job_details = job_details_iter->second;

  const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
      job_details.current_request_map[guid];
  DCHECK(request_info);
  DCHECK_EQ(guid, request_info->download_guid());

  request_info->PopulateWithResponse(std::move(response));

  if (job_details.controller)
    job_details.controller->DidStartRequest(request_info);
}

void BackgroundFetchDelegateProxy::DidActivateUI(
    const std::string& job_unique_id) {
  DCHECK(click_event_dispatcher_callback_);
  click_event_dispatcher_callback_.Run(job_unique_id);
}

void BackgroundFetchDelegateProxy::OnDownloadUpdated(
    const std::string& job_unique_id,
    const std::string& guid,
    uint64_t bytes_uploaded,
    uint64_t bytes_downloaded) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // TODO(delphick): The controller may not exist as persistence is not yet
  // implemented.
  auto job_details_iter = job_details_map_.find(job_unique_id);
  if (job_details_iter == job_details_map_.end())
    return;

  JobDetails& job_details = job_details_iter->second;

  // TODO(peter): Should we update the |request_info| with the progress?
  if (job_details.controller) {
    const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
        job_details.current_request_map[guid];
    DCHECK(request_info);
    DCHECK_EQ(guid, request_info->download_guid());
    job_details.controller->DidUpdateRequest(request_info, bytes_uploaded,
                                             bytes_downloaded);
  }
}

void BackgroundFetchDelegateProxy::OnDownloadComplete(
    const std::string& job_unique_id,
    const std::string& guid,
    std::unique_ptr<BackgroundFetchResult> result) {
  DCHECK_CURRENTLY_ON(BrowserThread::IO);

  // TODO(delphick): The controller may not exist as persistence is not yet
  // implemented.
  auto job_details_iter = job_details_map_.find(job_unique_id);
  if (job_details_iter == job_details_map_.end())
    return;

  JobDetails& job_details = job_details_iter->second;

  const scoped_refptr<BackgroundFetchRequestInfo>& request_info =
      job_details.current_request_map[guid];
  DCHECK(request_info);
  DCHECK_EQ(guid, request_info->download_guid());
  request_info->SetResult(std::move(result));

  if (job_details.controller)
    job_details.controller->DidCompleteRequest(request_info);
}

void BackgroundFetchDelegateProxy::GetUploadData(
    const std::string& job_unique_id,
    const std::string& download_guid,
    BackgroundFetchDelegate::GetUploadDataCallback callback) {
  auto& job_details = job_details_map_.find(job_unique_id)->second;
  DCHECK(job_details.controller);

  const auto& request =
      job_details.current_request_map[download_guid]->fetch_request_ptr();
  job_details.controller->GetUploadData(
      BackgroundFetchSettledFetch::CloneRequest(request), std::move(callback));
}

}  // namespace content
