Commit 6d0ed643 authored by John Williams's avatar John Williams Committed by Chromium LUCI CQ

[Media Router] Added a warning message about Castouts deprecation.

Bug: 1159209, b/1154342
Change-Id: I67f862c2f1e9cd2f8cfaeb2d73c5e22ebd360bb3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2559589Reviewed-by: default avatarTakumi Fujimoto <takumif@chromium.org>
Commit-Queue: John Williams <jrw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#837871}
parent 92a17fb7
......@@ -140,6 +140,14 @@ video files, instead of all files.">
No Thanks
</message>
<!-- Cast-to-meeting deprecation/removal -->
<message name="IDS_MEDIA_ROUTER_CAST_TO_MEETING_DEPRECATED" desc="Used in the Cast dialog to inform the user that starting a presentation from the Cast dialog will no longer work, and using meet.google.com will be the only option.">
Soon this option will no longer be supported. To present a tab, use <ph name="GOOGLE_MEET">$1<ex>Google Meet</ex></ph>.
</message>
<message name="IDS_MEDIA_ROUTER_CAST_TO_MEETING_REMOVED" desc="Used in the Cast dialog to inform the user that starting a presentation from the Cast dialog is not longer supported, and using meet.google.com is the only option.">
This option is no longer to supported. To present a tab, use <ph name="GOOGLE_MEET">$1<ex>Google Meet</ex></ph>.
</message>
<!-- Cloud Services Dialog -->
<message name="IDS_MEDIA_ROUTER_CLOUD_SERVICES_DIALOG_TITLE" desc="Title of the dialog asking whether the user wants to enable the feature allowing them to Cast to cloud services (Google Hangouts, Google Meet, Cast for Education extension).">
Enable cloud services for Cast?
......
375064581a249df7a570f0b38e5519416e009d4f
\ No newline at end of file
e549a37093dc3274b8345e414ac461ee6c53a287
\ No newline at end of file
......@@ -10,12 +10,19 @@
#include "base/strings/utf_string_conversions.h"
#include "build/branding_buildflags.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/media_router/ui_media_sink.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/chrome_typography.h"
#include "chrome/browser/ui/views/media_router/cast_dialog_helper.h"
#include "chrome/grit/generated_resources.h"
#include "components/media_router/common/issue.h"
#include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/l10n/l10n_util.h"
......@@ -27,6 +34,7 @@
#include "ui/views/controls/color_tracking_icon_view.h"
#include "ui/views/controls/styled_label.h"
#include "ui/views/controls/throbber.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/vector_icons.h"
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
......@@ -95,6 +103,99 @@ base::string16 GetStatusTextForSink(const UIMediaSink& sink) {
}
}
// Find the index of a tab whose URL matches the given origin and path. In the
// case of multiple matches, the active tab is given priority, otherwise returns
// the index of an arbitrary tab.
base::Optional<int> FindTabWithUrlPrefix(TabStripModel* tabs,
const GURL& origin,
base::StringPiece path) {
base::Optional<int> to_activate;
for (int i = 0; i < tabs->count(); i++) {
auto* content = tabs->GetWebContentsAt(i);
const GURL& url = content->GetVisibleURL();
if (url.GetOrigin() == origin && url.path() == path) {
to_activate = i;
if (tabs->active_index() <= i)
break;
}
}
return to_activate;
}
// Selects or creates a tab for a meeting ID. Tries to select an existing tab
// in the current window or some other window, and if no tab is found, opens a
// new tab for the meeting.
//
// If there is no meeting ID, this function just selects or creates a tab
// showing the start page of Google Meet.
void ShowMeetTab(Profile* profile,
const base::Optional<std::string>& meeting_id) {
const GURL origin("https://meet.google.com");
const std::string path = meeting_id ? "/" + *meeting_id : std::string();
const auto& browsers = *BrowserList::GetInstance();
for (auto iter = browsers.begin_last_active();
iter != browsers.end_last_active(); ++iter) {
Browser* browser = *iter;
if (browser->profile() == profile && browser->window() &&
browser->is_type_normal()) {
auto* tabs = browser->tab_strip_model();
auto tab_index = FindTabWithUrlPrefix(tabs, origin, path);
if (tab_index.has_value()) {
browser->window()->Show();
tabs->ActivateTabAt(tab_index.value());
return;
}
}
}
NavigateParams params(profile, origin.Resolve(path),
ui::PAGE_TRANSITION_FIRST);
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
Navigate(&params);
}
class CastToMeetingDeprecationWarningView : public views::View {
public:
CastToMeetingDeprecationWarningView(const std::string& sink_id,
Profile* profile) {
DCHECK(profile);
auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>());
layout->set_inside_border_insets(gfx::Insets(5));
layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kStart);
// Add space to line up with text in receiver list.
auto* spacer = AddChildView(std::make_unique<views::View>());
spacer->SetPreferredSize(gfx::Size(55, 1));
base::string16 text =
l10n_util::GetStringUTF16(IDS_MEDIA_ROUTER_CAST_TO_MEETING_DEPRECATED);
std::vector<base::string16> substrings{base::ASCIIToUTF16("Google Meet")};
std::vector<size_t> offsets;
text = base::ReplaceStringPlaceholders(text, substrings, &offsets);
auto* label = AddChildView(std::make_unique<views::StyledLabel>());
label->SetText(text);
// Try to extract a meeting ID from a sink ID. This should always succeed
// unless the "meeting" is actually a Hangout, or if the wrong version of
// the Cast extension is installed.
base::Optional<std::string> meeting_id;
if (sink_id.size() == 17 && base::StartsWith(sink_id, "meet:")) {
meeting_id = sink_id.substr(5);
}
gfx::Range link_range(offsets[0], offsets[0] + substrings[0].length());
auto link_style =
views::StyledLabel::RangeStyleInfo::CreateForLink(base::BindRepeating(
&ShowMeetTab, base::Unretained(profile), meeting_id));
link_style.disable_line_wrapping = false;
label->AddStyleRange(link_range, link_style);
}
};
} // namespace
CastDialogSinkButton::CastDialogSinkButton(PressedCallback callback,
......@@ -206,6 +307,19 @@ void CastDialogSinkButton::OnBlur() {
RestoreStatusText();
}
std::unique_ptr<views::View>
CastDialogSinkButton::MakeCastToMeetingDeprecationWarningView(
Profile* profile) {
switch (sink_.icon_type) {
case SinkIconType::MEETING:
case SinkIconType::HANGOUT:
return std::make_unique<CastToMeetingDeprecationWarningView>(sink_.id,
profile);
default:
return nullptr;
}
}
// static
const gfx::VectorIcon* CastDialogSinkButton::GetVectorIcon(
SinkIconType icon_type) {
......
......@@ -5,10 +5,14 @@
#ifndef CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_CAST_DIALOG_SINK_BUTTON_H_
#define CHROME_BROWSER_UI_VIEWS_MEDIA_ROUTER_CAST_DIALOG_SINK_BUTTON_H_
#include <memory>
#include "base/bind.h"
#include "chrome/browser/ui/media_router/ui_media_sink.h"
#include "chrome/browser/ui/views/hover_button.h"
class Profile;
namespace ui {
class MouseEvent;
}
......@@ -34,6 +38,13 @@ class CastDialogSinkButton : public HoverButton {
const UIMediaSink& sink() const { return sink_; }
// If this button will cast to a meeting, creates a view showing a warning
// about the feature being deprecated. Otherwise returns nullptr. The
// |profile| parameter is used to open the meeting tab the the user clicks on
// the link in the warning.
std::unique_ptr<views::View> MakeCastToMeetingDeprecationWarningView(
Profile* profile);
static const gfx::VectorIcon* GetVectorIcon(SinkIconType icon_type);
private:
......
......@@ -223,6 +223,7 @@ CastDialogView::CastDialogView(views::View* anchor_view,
controller_(controller),
profile_(profile),
metrics_(start_time, activation_location, profile) {
DCHECK(profile);
SetShowCloseButton(true);
SetButtons(ui::DIALOG_BUTTON_NONE);
set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(
......@@ -319,11 +320,22 @@ void CastDialogView::PopulateScrollView(const std::vector<UIMediaSink>& sinks) {
sink_list_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
for (size_t i = 0; i < sinks.size(); i++) {
sink_buttons_.push_back(
auto* sink_button =
sink_list_view->AddChildView(std::make_unique<CastDialogSinkButton>(
base::BindRepeating(&CastDialogView::SinkPressed,
base::Unretained(this), i),
sinks.at(i))));
sinks.at(i)));
sink_buttons_.push_back(sink_button);
// This could potentially add a lot of warnings to the receiver list, but in
// practice a user is unlikely to have more than one or two meetings in the
// list at any given time, and repeating the warning is probably better than
// having the user ignore possibly the warning if it's only shown for a
// meeting they're not trying to cast to.
auto warning_view =
sink_button->MakeCastToMeetingDeprecationWarningView(profile_);
if (warning_view)
sink_list_view->AddChildView(std::move(warning_view));
}
scroll_view_->SetContents(std::move(sink_list_view));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment