blob: d5097e4831f956dc259f899054c4e8bc281d5827 [file] [log] [blame]
// 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.
#include "chrome/browser/devtools/process_sharing_infobar_delegate.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/grit/generated_resources.h"
#include "components/infobars/core/infobar.h"
#include "components/webui/flags/pref_service_flags_storage.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/mojom/dialog_button.mojom.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/window/dialog_delegate.h"
namespace {
std::unique_ptr<views::View> MakeRestartView() {
auto view = std::make_unique<views::View>();
views::LayoutProvider* provider = views::LayoutProvider::Get();
view->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical,
provider->GetInsetsMetric(views::InsetsMetric::INSETS_DIALOG),
provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)));
const std::u16string message = l10n_util::GetStringUTF16(
IDS_DEV_TOOLS_SHARED_PROCESS_INFOBAR_RESTART_NEEDED);
views::Label* message_label = new views::Label(message);
message_label->SetMultiLine(true);
message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
view->AddChildViewRaw(message_label);
return view;
}
} // namespace
ProcessSharingInfobarDelegate::ProcessSharingInfobarDelegate(
content::WebContents* web_contents)
: inspected_web_contents_(web_contents->GetWeakPtr()) {}
ProcessSharingInfobarDelegate::~ProcessSharingInfobarDelegate() = default;
std::u16string ProcessSharingInfobarDelegate::GetMessageText() const {
return l10n_util::GetStringUTF16(IDS_DEV_TOOLS_SHARED_PROCESS_INFOBAR);
}
int ProcessSharingInfobarDelegate::GetButtons() const {
return BUTTON_OK;
}
std::u16string ProcessSharingInfobarDelegate::GetButtonLabel(
InfoBarButton button) const {
DCHECK_EQ(BUTTON_OK, button);
return l10n_util::GetStringUTF16(
IDS_DEV_TOOLS_SHARED_PROCESS_INFOBAR_OPT_OUT);
}
std::u16string ProcessSharingInfobarDelegate::GetLinkText() const {
return l10n_util::GetStringUTF16(
IDS_DEV_TOOLS_SHARED_PROCESS_INFOBAR_LEARN_MORE);
}
GURL ProcessSharingInfobarDelegate::GetLinkURL() const {
return GURL("https://developer.chrome.com/blog/process-sharing-experiment");
}
infobars::InfoBarDelegate::InfoBarIdentifier
ProcessSharingInfobarDelegate::GetIdentifier() const {
return DEV_TOOLS_SHARED_PROCESS_DELEGATE;
}
bool ProcessSharingInfobarDelegate::Accept() {
if (!inspected_web_contents_) {
return true;
}
auto delegate = std::make_unique<views::DialogDelegate>();
delegate->set_internal_name("ProcessSharingAppRestart");
delegate->SetButtons(static_cast<int>(ui::mojom::DialogButton::kOk) |
static_cast<int>(ui::mojom::DialogButton::kCancel));
delegate->SetContentsView(MakeRestartView());
delegate->SetModalType(ui::mojom::ModalType::kSystem);
delegate->SetOwnedByWidget(views::WidgetDelegate::OwnedByWidgetPassKey());
delegate->SetShowCloseButton(false);
delegate->set_fixed_width(ChromeLayoutProvider::Get()->GetDistanceMetric(
views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
delegate->SetAcceptCallback(base::BindOnce(
[](base::WeakPtr<content::WebContents> inspected_web_contents) {
#if BUILDFLAG(IS_CHROMEOS)
PrefService* prefs = Profile::FromBrowserContext(
inspected_web_contents->GetBrowserContext())
->GetPrefs();
#else
PrefService* prefs = g_browser_process->local_state();
#endif
// Note: Both ChromeOS owner and non-owner use PrefServiceFlagsStorage
// under the hood. OwnersFlagsStorage has additional functionalities
// for setting flags but since we are just reading the storage assume
// non-owner case and bypass asynchronous owner check.
auto flags_storage =
std::make_unique<flags_ui::PrefServiceFlagsStorage>(prefs);
about_flags::SetFeatureEntryEnabled(
flags_storage.get(),
"enable-process-per-site-up-to-main-frame-threshold@2", true);
flags_storage->CommitPendingWrites();
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&chrome::AttemptRestart));
},
inspected_web_contents_));
views::DialogDelegate::CreateDialogWidget(
std::move(delegate), inspected_web_contents_->GetTopLevelNativeWindow(),
gfx::NativeView())
->Show();
return ConfirmInfoBarDelegate::Accept();
}