chromium/ios/chrome/browser/download/model/document_download_tab_helper.h

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef IOS_CHROME_BROWSER_DOWNLOAD_MODEL_DOCUMENT_DOWNLOAD_TAB_HELPER_H_
#define IOS_CHROME_BROWSER_DOWNLOAD_MODEL_DOCUMENT_DOWNLOAD_TAB_HELPER_H_

#import <Foundation/Foundation.h>

#import "ios/web/public/download/download_task.h"
#import "ios/web/public/download/download_task_observer.h"
#import "ios/web/public/web_state.h"
#import "ios/web/public/web_state_observer.h"
#import "ios/web/public/web_state_user_data.h"

// DocumentDownloadTabHelper that triggers download tasks on non-HTML and
// non-Video files. Video are not supported as they appear in fullscreen an the
// download bar is not visible.
class DocumentDownloadTabHelper
    : public web::WebStateObserver,
      public web::DownloadTaskObserver,
      public web::WebStateUserData<DocumentDownloadTabHelper> {
 public:
  DocumentDownloadTabHelper(const DocumentDownloadTabHelper&) = delete;
  DocumentDownloadTabHelper& operator=(const DocumentDownloadTabHelper&) =
      delete;
  explicit DocumentDownloadTabHelper(web::WebState* web_state);

  ~DocumentDownloadTabHelper() override;

  // Returns whether the current download task was created by this TabHelper.
  bool IsDownloadTaskCreatedByCurrentTabHelper();

  // web::WebStateObserver implementation.
  void WebStateDestroyed(web::WebState* web_state) override;
  void PageLoaded(
      web::WebState* web_state,
      web::PageLoadCompletionStatus load_completion_status) override;
  void DidStartNavigation(web::WebState* web_state,
                          web::NavigationContext* navigation_context) override;
  void DidFinishNavigation(web::WebState* web_state,
                           web::NavigationContext* navigation_context) override;
  void WasShown(web::WebState* web_state) override;
  void WasHidden(web::WebState* web_state) override;

  // web::DownloadTaskObserver overrides:
  void OnDownloadDestroyed(web::DownloadTask* task) override;
  void OnDownloadUpdated(web::DownloadTask* task) override;

 private:
  friend class web::WebStateUserData<DocumentDownloadTabHelper>;

  // Attach the fullscreen observation to the toolbar UI.
  void AttachFullscreen();

  // Detach the fullscreen observation from the toolbar UI.
  void DetachFullscreen();

  // Used in the case when the task created to download the document is queued.
  // In that case, the current task is observed and `OnPreviousTaskDeleted` is
  // called on the task deletion.
  void OnPreviousTaskDeleted();

  // The webState this TabHelper is attached to.
  raw_ptr<web::WebState> web_state_;

  // Whether the task has been created for the current navigation.
  NSString* task_uuid_ = nil;

  // Whether the download should be triggered but there is already an ongoing
  // task.
  bool waiting_for_previous_task_ = false;

  // Whether `observed_task_` was created by this TabHelper.
  bool current_task_is_document_download_ = false;

  // The download task that is currently observed. Kept for cleanup purpose.
  raw_ptr<web::DownloadTask> observed_task_;

  // The current state of the `observed_task_`.
  // This is used to track the state before it is set to `kCancelled` for
  // destruction.
  web::DownloadTask::State observed_task_state_ =
      web::DownloadTask::State::kNotStarted;

  // The size of the file in bytes, if reported in the response headers.
  int64_t file_size_ = -1;

  WEB_STATE_USER_DATA_KEY_DECL();

  base::WeakPtrFactory<DocumentDownloadTabHelper> weak_ptr_factory_{this};
};

#endif  // IOS_CHROME_BROWSER_DOWNLOAD_MODEL_DOCUMENT_DOWNLOAD_TAB_HELPER_H_