blob: 25d20ef61b46dcde84a0404e258a72d7879cd09f [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PRINTING_PRINT_PREVIEW_DIALOG_CONTROLLER_H_
#define CHROME_BROWSER_PRINTING_PRINT_PREVIEW_DIALOG_CONTROLLER_H_
#include <map>
#include "base/check.h"
#include "base/functional/callback.h"
#include "chrome/browser/tab_contents/web_contents_collection.h"
#include "components/printing/common/print.mojom.h"
class GURL;
namespace content {
class WebContents;
}
namespace printing {
// For print preview, the WebContents that initiates the printing operation is
// the initiator, and the constrained dialog that shows the print preview is the
// print preview dialog.
// This class manages print preview dialog creation and destruction, and keeps
// track of the 1:1 relationship between initiator tabs and print preview
// dialogs.
class PrintPreviewDialogController : public WebContentsCollection::Observer {
public:
// Should only be used by `BrowserProcess`-like classes. Call `GetInstance()`
// to get the active instance.
PrintPreviewDialogController();
PrintPreviewDialogController(const PrintPreviewDialogController&) = delete;
PrintPreviewDialogController& operator=(const PrintPreviewDialogController&) =
delete;
~PrintPreviewDialogController() override;
// Returns the existing instance in the global `BrowserProcess`.
static PrintPreviewDialogController* GetInstance();
// Returns true if `url` is a Print Preview dialog URL (has `chrome://print`
// origin).
static bool IsPrintPreviewURL(const GURL& url);
// Returns true if `url` is a Print Preview content URL (has
// `chrome-untrusted://print` origin).
static bool IsPrintPreviewContentURL(const GURL& url);
// Initiates print preview for `initiator`.
void PrintPreview(content::WebContents* initiator,
const mojom::RequestPrintPreviewParams& params);
// Returns the preview dialog for `contents`.
// Returns `contents` if `contents` is a preview dialog.
// Returns nullptr if no preview dialog exists for `contents`.
content::WebContents* GetPrintPreviewForContents(
content::WebContents* contents) const;
// Returns the initiator for `preview_dialog`.
// Returns nullptr if no initiator exists for `preview_dialog`.
content::WebContents* GetInitiator(content::WebContents* preview_dialog);
// Returns the request data associated with `preview_dialog`.
// Returns nullptr if no data exists for `preview_dialog`.
const mojom::RequestPrintPreviewParams* GetRequestParams(
content::WebContents* preview_dialog) const;
// Runs `callback` on the dialog of each active print preview operation.
void ForEachPreviewDialog(
base::RepeatingCallback<void(content::WebContents*)> callback);
// Erases the initiator info associated with `preview_dialog`.
void EraseInitiatorInfo(content::WebContents* preview_dialog);
// Exposes GetOrCreatePreviewDialog() for testing.
content::WebContents* GetOrCreatePreviewDialogForTesting(
content::WebContents* initiator);
#if defined(UNIT_TEST)
// Exposes a way for tests to manually specify the initiator to preview_dialog
// relationship. For use in tests that create their own preview dialogs.
void AssociateWebContentsesForTesting(content::WebContents* initiator,
content::WebContents* preview_dialog) {
CHECK(initiator);
CHECK(preview_dialog);
preview_dialog_map_[preview_dialog].initiator = initiator;
preview_dialog_map_[preview_dialog].request_params.is_modifiable = true;
}
void DisassociateWebContentsesForTesting(
content::WebContents* preview_dialog) {
CHECK(preview_dialog);
size_t erased_count = preview_dialog_map_.erase(preview_dialog);
CHECK(erased_count);
}
#endif
bool is_creating_print_preview_dialog() const {
return is_creating_print_preview_dialog_;
}
private:
// Tracks the initiator, as well as some of its Print Preview properties.
struct InitiatorData {
raw_ptr<content::WebContents> initiator;
mojom::RequestPrintPreviewParams request_params;
};
// 1:1 relationship between a print preview dialog and its initiator data.
// Key: Print preview dialog.
// Value: Initiator data.
using PrintPreviewDialogMap = std::map<content::WebContents*, InitiatorData>;
// WebContentsCollection::Observer:
// Handles the closing of the RenderProcessHost. This is observed when the
// initiator renderer crashes.
void RenderProcessGone(content::WebContents* contents,
base::TerminationStatus status) override;
// Handles the destruction of `contents`. This is observed when either
// the initiator or preview WebContents is closed.
void WebContentsDestroyed(content::WebContents* contents) override;
// Handles the commit of a navigation for `contents`. This is observed when
// the renderer for either WebContents is navigated to a different page.
void DidFinishNavigation(
content::WebContents* contents,
content::NavigationHandle* navigation_handle) override;
// Helpers for DidFinishNavigation().
void OnInitiatorNavigated(content::WebContents* initiator,
content::NavigationHandle* navigation_handle);
void OnPreviewDialogNavigated(content::WebContents* preview_dialog,
content::NavigationHandle* navigation_handle);
// Gets/Creates the print preview dialog for `initiator`.
content::WebContents* GetOrCreatePreviewDialog(
content::WebContents* initiator,
const mojom::RequestPrintPreviewParams& params);
// Creates a new print preview dialog if GetOrCreatePreviewDialog() cannot
// find a print preview dialog for `initiator`.
content::WebContents* CreatePrintPreviewDialog(
content::WebContents* initiator,
const mojom::RequestPrintPreviewParams& params);
// Helper function to store the title of the initiator associated with
// `preview_dialog` in `preview_dialog`'s PrintPreviewUI.
void SaveInitiatorTitle(content::WebContents* preview_dialog);
// Removes WebContents when they close/crash/navigate.
void RemoveInitiator(content::WebContents* initiator);
void RemovePreviewDialog(content::WebContents* preview_dialog);
// Mapping between print preview dialog and the corresponding initiator.
PrintPreviewDialogMap preview_dialog_map_;
WebContentsCollection web_contents_collection_;
// Whether the PrintPreviewDialogController is in the middle of creating a
// print preview dialog.
bool is_creating_print_preview_dialog_ = false;
};
} // namespace printing
#endif // CHROME_BROWSER_PRINTING_PRINT_PREVIEW_DIALOG_CONTROLLER_H_