Skip to content

Commit

Permalink
[Media Router] Custom Controls 4 - Implement details view WebUI
Browse files Browse the repository at this point in the history
This CL adds a built-in alternative to the extensionview controller in the route
details view of the media router dialog WebUI. The WebUI route controller is
functionally equivalent to the extensionview controller.

Whenever the WebUI is notified by the browser process of updates to the media
status of the shown route, the details view is updated. Whenever the user
interacts with the media controls on the details view, the media commands are
sent to the browser process.

The switch to the WebUI controller is managed by a Finch experiment that is
currently disabled, so this CL has no behavioral change. Its functionality can
be checked out with the flag --enable-features=MediaRouterUIRouteController.

Before-and-after screenshots:
https://docs.google.com/document/d/1v8jGV33FiFtH_qs2_Ui0UNubt1nHRN_CBrHLt1wRXF0

The Chromium-side implementation of custom controls will be done in these
patches:
1. Mojo/MediaStatus/MediaRouteController:     http://crrev/2727123002
2. MediaRouter::GetRouteController():         http://crrev/2728543009
3. MRUI/MRWebUIMessageHandler:                http://crrev/2731033002
4. Custom controls WebUI:                     this patch

Custom controls design doc:
https://docs.google.com/document/d/1_8QxdFIiiJX39jR1Wi1Zn9FW-Y66EMvX1GmQZvjN4G0/edit

[1] https://codereview.chromium.org/2724513002/

BUG=684633
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2725503002
Cr-Commit-Position: refs/heads/master@{#475667}
  • Loading branch information
takumif authored and Commit Bot committed May 30, 2017
1 parent 5620d9e commit 3f79238
Show file tree
Hide file tree
Showing 34 changed files with 1,757 additions and 383 deletions.
18 changes: 18 additions & 0 deletions chrome/app/media_router_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,24 @@
<message name="IDS_MEDIA_ROUTER_STOP_CASTING_BUTTON" desc="Stop casting button, which, on click, will stop the current route.">
Stop
</message>
<message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_PLAY_TITLE" desc="The title label for a button to play media contents.">
Play
</message>
<message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_PAUSE_TITLE" desc="The title label for a button to pause media contents.">
Pause
</message>
<message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_MUTE_TITLE" desc="The title label for a button to mute media contents.">
Mute
</message>
<message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_UNMUTE_TITLE" desc="The title label for a button to unmute media contents.">
Unmute
</message>
<message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_SEEK_TITLE" desc="The title label for a seek bar for media contents.">
Seek
</message>
<message name="IDS_MEDIA_ROUTER_ROUTE_DETAILS_VOLUME_TITLE" desc="The title label for a volume control bar for media contents.">
Volume
</message>

<!-- Sink List -->
<message name="IDS_MEDIA_ROUTER_DESTINATION_MISSING" desc="Link to display when no Cast destinations are found which, on click, opens a page to the Chromecast help center explaining possible reasons why none are detected.">
Expand Down
6 changes: 6 additions & 0 deletions chrome/browser/media_router_resources.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
<include name="IDR_MEDIA_ROUTER_SEARCH_HIGHLIGHTER_CSS" file="resources\media_router\elements\media_router_search_highlighter\media_router_search_highlighter.css" type="BINDATA" />
<include name="IDR_MEDIA_ROUTER_SEARCH_HIGHLIGHTER_HTML" file="resources\media_router\elements\media_router_search_highlighter\media_router_search_highlighter.html" type="BINDATA" />
<include name="IDR_MEDIA_ROUTER_SEARCH_HIGHLIGHTER_JS" file="resources\media_router\elements\media_router_search_highlighter\media_router_search_highlighter.js" type="BINDATA" />
<include name="IDR_ROUTE_CONTROLS_HTML" file="resources\media_router\elements\route_controls\route_controls.html" type="BINDATA" />
<include name="IDR_ROUTE_CONTROLS_CSS" file="resources\media_router\elements\route_controls\route_controls.css" type="BINDATA" />
<include name="IDR_ROUTE_CONTROLS_JS" file="resources\media_router\elements\route_controls\route_controls.js" type="BINDATA" />
<include name="IDR_EXTENSION_VIEW_WRAPPER_HTML" file="resources\media_router\elements\route_details\extension_view_wrapper\extension_view_wrapper.html" type="BINDATA" />
<include name="IDR_EXTENSION_VIEW_WRAPPER_CSS" file="resources\media_router\elements\route_details\extension_view_wrapper\extension_view_wrapper.css" type="BINDATA" />
<include name="IDR_EXTENSION_VIEW_WRAPPER_JS" file="resources\media_router\elements\route_details\extension_view_wrapper\extension_view_wrapper.js" type="BINDATA" />
<include name="IDR_ROUTE_DETAILS_HTML" file="resources\media_router\elements\route_details\route_details.html" type="BINDATA" />
<include name="IDR_ROUTE_DETAILS_CSS" file="resources\media_router\elements\route_details\route_details.css" type="BINDATA" />
<include name="IDR_ROUTE_DETAILS_JS" file="resources\media_router\elements\route_details\route_details.js" type="BINDATA" />
Expand Down
13 changes: 11 additions & 2 deletions chrome/browser/resources/media_router/compiled_resources2.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'media_router_browser_api',
'dependencies': [
'media_router_data',
'<(EXTERNS_GYP):chrome_send',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'media_router_data',
'dependencies': [
Expand All @@ -28,9 +36,10 @@
{
'target_name': 'media_router_ui_interface',
'dependencies': [
'<(EXTERNS_GYP):chrome_send',
'media_router_browser_api',
'elements/media_router_header/compiled_resources2.gyp:media_router_header',
'elements/media_router_container/compiled_resources2.gyp:media_router_container',
'elements/media_router_container/compiled_resources2.gyp:media_router_container_interface',
'elements/route_controls/compiled_resources2.gyp:route_controls_interface',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
'dependencies': [
'pseudo_sink_search_state',
'../../compiled_resources2.gyp:externs',
'../../compiled_resources2.gyp:media_router_browser_api',
'../../compiled_resources2.gyp:media_router_data',
'../../elements/issue_banner/compiled_resources2.gyp:issue_banner',
'../../elements/media_router_header/compiled_resources2.gyp:media_router_header',
Expand All @@ -16,6 +17,13 @@
],
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'media_router_container_interface',
'dependencies': [
'../../compiled_resources2.gyp:media_router_data',
],
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'pseudo_sink_search_state',
'dependencies': [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@
is-any-sink-currently-launching=
"[[computeIsLaunching_(currentLaunchingSinkId_)]]"
on-change-route-source-click="onChangeRouteSourceClick_"
on-close-route="onCloseRoute_">
on-close-route="onCloseRoute_"
use-web-ui-route-controls="[[useWebUiRouteControls]]">
</route-details>
</template>
<div id="sink-list-view"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This Polymer element contains the entire media router interface. It handles
// hiding and showing specific components.
/**
* This Polymer element contains the entire media router interface. It handles
* hiding and showing specific components.
* @implements {MediaRouterContainerInterface}
*/
Polymer({
is: 'media-router-container',

Expand Down Expand Up @@ -386,6 +389,16 @@ Polymer({
observer: 'updateElementPositioning_',
},

/**
* Whether the WebUI route controls should be shown instead of the
* extensionview in the route details view.
* @type {boolean}
*/
useWebUiRouteControls: {
type: Boolean,
value: false,
},

/**
* Whether the user has explicitly selected a cast mode.
* @private {boolean}
Expand Down Expand Up @@ -864,8 +877,8 @@ Polymer({
* @return {boolean} Whether the search results list should be hidden.
* @private
*/
computeSearchResultsHidden_: function(searchResultsToShow,
isSearchListHidden) {
computeSearchResultsHidden_: function(
searchResultsToShow, isSearchListHidden) {
return isSearchListHidden || searchResultsToShow.length == 0;
},

Expand Down Expand Up @@ -1081,14 +1094,22 @@ Polymer({
* filter action here.
* @param {?media_router.MediaRouterView} currentView The current view of the
* dialog.
* @param {?media_router.MediaRouterView} previousView The previous
* |currentView|.
* @private
*/
currentViewChanged_: function(currentView) {
currentViewChanged_: function(currentView, previousView) {
if (currentView == media_router.MediaRouterView.FILTER) {
this.reportFilterOnInput_ = true;
this.maybeReportFilter_();
}
this.updateElementPositioning_();

if (previousView == media_router.MediaRouterView.ROUTE_DETAILS) {
media_router.browserApi.onMediaControllerClosed();
if (this.$$('route-details'))
this.$$('route-details').onClosed();
}
},

/**
Expand Down Expand Up @@ -1767,6 +1788,18 @@ Polymer({
}
},

/**
* Called when the connection to the route controller is invalidated. Switches
* from route details view to the sink list view.
*/
onRouteControllerInvalidated: function() {
if (this.useWebUiRouteControls &&
this.currentView_ == media_router.MediaRouterView.ROUTE_DETAILS) {
this.currentRoute_ = null;
this.showSinkList_();
}
},

/**
* Called when a sink is clicked.
*
Expand Down Expand Up @@ -2279,6 +2312,12 @@ Polymer({
showRouteDetails_: function(route) {
this.currentRoute_ = route;
this.currentView_ = media_router.MediaRouterView.ROUTE_DETAILS;
if (this.useWebUiRouteControls) {
media_router.browserApi.onMediaControllerAvailable(route.id);
}
if (this.$$('route-details')) {
this.$$('route-details').onOpened();
}
},

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
* This Polymer element contains the entire media router interface. It handles
* hiding and showing specific components.
* @record
*/
function MediaRouterContainerInterface() {}

/**
* The list of available sinks.
* @type {!Array<!media_router.Sink>}
*/
MediaRouterContainerInterface.prototype.allSinks;

/**
* The list of CastModes to show.
* @type {!Array<!media_router.CastMode>|undefined}
*/
MediaRouterContainerInterface.prototype.castModeList;

/**
* The URL to open when the device missing link is clicked.
* @type {string|undefined}
*/
MediaRouterContainerInterface.prototype.deviceMissingUrl;

/**
* The URL to open when the cloud services pref learn more link is clicked.
* @type {string|undefined}
*/
MediaRouterContainerInterface.prototype.firstRunFlowCloudPrefLearnMoreUrl;

/**
* The URL to open when the first run flow learn more link is clicked.
* @type {string|undefined}
*/
MediaRouterContainerInterface.prototype.firstRunFlowLearnMoreUrl;

/**
* The header text for the sink list.
* @type {string|undefined}
*/
MediaRouterContainerInterface.prototype.headerText;

/**
* The header text tooltip. This would be descriptive of the
* source origin, whether a host name, tab URL, etc.
* @type {string|undefined}
*/
MediaRouterContainerInterface.prototype.headerTextTooltip;

/**
* The issue to show.
* @type {?media_router.Issue}
*/
MediaRouterContainerInterface.prototype.issue;

/**
* The list of current routes.
* @type {!Array<!media_router.Route>|undefined}
*/
MediaRouterContainerInterface.prototype.routeList;

/**
* Whether the search input should be padded as if it were at the bottom of
* the dialog.
* @type {boolean}
*/
MediaRouterContainerInterface.prototype.searchUseBottomPadding;

/**
* Whether to show the user domain of sinks associated with identity.
* @type {boolean|undefined}
*/
MediaRouterContainerInterface.prototype.showDomain;

/**
* Whether to show the first run flow.
* @type {boolean|undefined}
*/
MediaRouterContainerInterface.prototype.showFirstRunFlow;

/**
* Whether to show the cloud preference setting in the first run flow.
* @type {boolean|undefined}
*/
MediaRouterContainerInterface.prototype.showFirstRunFlowCloudPref;

/**
* Whether the WebUI route controls should be shown instead of the
* extensionview in the route details view.
* @type {boolean}
*/
MediaRouterContainerInterface.prototype.useWebUiRouteControls;

/**
* Fires a 'report-initial-action' event when the user takes their first
* action after the dialog opens. Also fires a 'report-initial-action-close'
* event if that initial action is to close the dialog.
* @param {!media_router.MediaRouterUserAction} initialAction
*/
MediaRouterContainerInterface.prototype.maybeReportUserFirstAction = function(
initialAction) {};

/**
* Updates |currentView_| if the dialog had just opened and there's
* only one local route.
*/
MediaRouterContainerInterface.prototype.maybeShowRouteDetailsOnOpen =
function() {};

/**
* Handles response of previous create route attempt.
* @param {string} sinkId The ID of the sink to which the Media Route was
* creating a route.
* @param {?media_router.Route} route The newly created route that
* corresponds to the sink if route creation succeeded; null otherwise.
* @param {boolean} isForDisplay Whether or not |route| is for display.
*/
MediaRouterContainerInterface.prototype.onCreateRouteResponseReceived =
function(sinkId, route, isForDisplay) {};

/**
* Called when a search has completed up to route creation. |sinkId|
* identifies the sink that should be in |allSinks|, if a sink was found.
* @param {string} sinkId The ID of the sink that is the result of the
* currently pending search.
*/
MediaRouterContainerInterface.prototype.onReceiveSearchResult = function(
sinkId) {};

/**
* Called when the connection to the route controller is invalidated. Switches
* from route details view to the sink list view.
*/
MediaRouterContainerInterface.prototype.onRouteControllerInvalidated =
function() {};

/**
* Sets the selected cast mode to the one associated with |castModeType|,
* and rebuilds sinks to reflect the change.
* @param {number} castModeType The type of the selected cast mode.
*/
MediaRouterContainerInterface.prototype.selectCastMode = function(
castModeType) {};

/**
* Update the max dialog height and update the positioning of the elements.
* @param {number} height The max height of the Media Router dialog.
*/
MediaRouterContainerInterface.prototype.updateMaxDialogHeight = function(
height) {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'targets': [
{
'target_name': 'route_controls',
'dependencies': [
'../../compiled_resources2.gyp:media_router_browser_api',
'../../compiled_resources2.gyp:media_router_data',
'../../compiled_resources2.gyp:media_router_ui_interface',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
],
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'route_controls_interface',
'dependencies': [
'../../compiled_resources2.gyp:media_router_data',
],
'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
],
}
Loading

0 comments on commit 3f79238

Please sign in to comment.