1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h"
6 
7 #include "ash/public/cpp/shell_window_ids.h"
8 #include "ash/public/cpp/window_backdrop.h"
9 #include "ash/public/cpp/window_properties.h"
10 #include "base/bind.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/system/sys_info.h"
13 #include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_service_factory.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/profiles/profile_manager.h"
16 #include "chrome/browser/ui/browser_dialogs.h"
17 #include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_handler.h"
18 #include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.h"
19 #include "chrome/browser/ui/webui/metrics_handler.h"
20 #include "chrome/common/url_constants.h"
21 #include "chrome/common/webui_url_constants.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "chrome/grit/multidevice_setup_resources.h"
24 #include "chrome/grit/multidevice_setup_resources_map.h"
25 #include "chromeos/grit/chromeos_resources.h"
26 #include "chromeos/services/multidevice_setup/multidevice_setup_service.h"
27 #include "chromeos/services/multidevice_setup/public/cpp/url_provider.h"
28 #include "components/strings/grit/components_strings.h"
29 #include "content/public/browser/web_ui.h"
30 #include "content/public/browser/web_ui_data_source.h"
31 #include "ui/aura/window.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/gfx/native_widget_types.h"
34 
35 namespace chromeos {
36 
37 namespace multidevice_setup {
38 
39 namespace {
40 
41 constexpr int kPreferredDialogHeightPx = 640;
42 constexpr int kPreferredDialogWidthPx = 768;
43 
44 }  // namespace
45 
46 // static
47 MultiDeviceSetupDialog* MultiDeviceSetupDialog::current_instance_ = nullptr;
48 
49 // static
Show()50 void MultiDeviceSetupDialog::Show() {
51   // The dialog is already showing, so there is nothing to do.
52   if (current_instance_)
53     return;
54 
55   current_instance_ = new MultiDeviceSetupDialog();
56   gfx::NativeWindow window = chrome::ShowWebDialog(
57       nullptr /* parent */, ProfileManager::GetActiveUserProfile(),
58       current_instance_);
59 
60   // Remove the black backdrop behind the dialog window which appears in tablet
61   // and full-screen mode.
62   ash::WindowBackdrop::Get(window)->SetBackdropMode(
63       ash::WindowBackdrop::BackdropMode::kDisabled);
64 }
65 
66 // static
Get()67 MultiDeviceSetupDialog* MultiDeviceSetupDialog::Get() {
68   return current_instance_;
69 }
70 
71 // static
SetInstanceForTesting(MultiDeviceSetupDialog * instance)72 void MultiDeviceSetupDialog::SetInstanceForTesting(
73     MultiDeviceSetupDialog* instance) {
74   current_instance_ = instance;
75 }
76 
AddOnCloseCallback(base::OnceClosure callback)77 void MultiDeviceSetupDialog::AddOnCloseCallback(base::OnceClosure callback) {
78   on_close_callbacks_.push_back(std::move(callback));
79 }
80 
MultiDeviceSetupDialog()81 MultiDeviceSetupDialog::MultiDeviceSetupDialog()
82     : SystemWebDialogDelegate(GURL(chrome::kChromeUIMultiDeviceSetupUrl),
83                               base::string16()) {}
84 
~MultiDeviceSetupDialog()85 MultiDeviceSetupDialog::~MultiDeviceSetupDialog() {
86   for (auto& callback : on_close_callbacks_)
87     std::move(callback).Run();
88 }
89 
GetDialogSize(gfx::Size * size) const90 void MultiDeviceSetupDialog::GetDialogSize(gfx::Size* size) const {
91   // Note: The size is calculated once based on the current screen orientation
92   // and is not ever updated. It might be possible to resize the dialog upon
93   // each screen rotation, but https://crbug.com/1030993 prevents this from
94   // working.
95   // TODO(https://crbug.com/1030993): Explore resizing the dialog dynamically.
96   static const gfx::Size dialog_size = ComputeDialogSizeForInternalScreen(
97       gfx::Size(kPreferredDialogWidthPx, kPreferredDialogHeightPx));
98   size->SetSize(dialog_size.width(), dialog_size.height());
99 }
100 
OnDialogClosed(const std::string & json_retval)101 void MultiDeviceSetupDialog::OnDialogClosed(const std::string& json_retval) {
102   DCHECK(this == current_instance_);
103   current_instance_ = nullptr;
104 
105   // Note: The call below deletes |this|, so there is no further need to keep
106   // track of the pointer.
107   SystemWebDialogDelegate::OnDialogClosed(json_retval);
108 }
109 
MultiDeviceSetupDialogUI(content::WebUI * web_ui)110 MultiDeviceSetupDialogUI::MultiDeviceSetupDialogUI(content::WebUI* web_ui)
111     : ui::MojoWebDialogUI(web_ui) {
112   content::WebUIDataSource* source =
113       content::WebUIDataSource::Create(chrome::kChromeUIMultiDeviceSetupHost);
114 
115   source->DisableTrustedTypesCSP();
116 
117   chromeos::multidevice_setup::AddLocalizedStrings(source);
118   source->UseStringsJs();
119   source->SetDefaultResource(
120       IDR_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DIALOG_HTML);
121 
122   // Note: The |kMultiDeviceSetupResourcesSize| and |kMultideviceSetupResources|
123   // fields are defined in the generated file
124   // chrome/grit/multidevice_setup_resources_map.h.
125   for (size_t i = 0; i < kMultideviceSetupResourcesSize; ++i) {
126     source->AddResourcePath(kMultideviceSetupResources[i].name,
127                             kMultideviceSetupResources[i].value);
128   }
129 
130   web_ui->AddMessageHandler(std::make_unique<MultideviceSetupHandler>());
131   web_ui->AddMessageHandler(std::make_unique<MetricsHandler>());
132   content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
133 }
134 
135 MultiDeviceSetupDialogUI::~MultiDeviceSetupDialogUI() = default;
136 
BindInterface(mojo::PendingReceiver<chromeos::multidevice_setup::mojom::MultiDeviceSetup> receiver)137 void MultiDeviceSetupDialogUI::BindInterface(
138     mojo::PendingReceiver<chromeos::multidevice_setup::mojom::MultiDeviceSetup>
139         receiver) {
140   MultiDeviceSetupService* service =
141       MultiDeviceSetupServiceFactory::GetForProfile(
142           Profile::FromWebUI(web_ui()));
143   if (service)
144     service->BindMultiDeviceSetup(std::move(receiver));
145 }
146 
147 WEB_UI_CONTROLLER_TYPE_IMPL(MultiDeviceSetupDialogUI)
148 
149 }  // namespace multidevice_setup
150 
151 }  // namespace chromeos
152