Commit e3009cc8 authored by Matt Menard's avatar Matt Menard Committed by Chromium LUCI CQ

Use PrintServerStore in CrOS destination-dialog

Bug: b:168650771
Change-Id: Ib71d53ef4aca5c08521e8478ca15007d60d6640d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2545669
Commit-Queue: Matt Menard <mattme@google.com>
Reviewed-by: default avatarRebekah Potter <rbpotter@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834786}
parent aea4c899
...@@ -461,10 +461,13 @@ if (is_chromeos_ash) { ...@@ -461,10 +461,13 @@ if (is_chromeos_ash) {
"../data:destination", "../data:destination",
"../data:destination_store", "../data:destination_store",
"../data:invitation_store", "../data:invitation_store",
"../data:print_server_store",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
"//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m", "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
"//ui/webui/resources/cr_elements/cr_searchable_drop_down:cr_searchable_drop_down.m",
"//ui/webui/resources/js:event_tracker.m", "//ui/webui/resources/js:event_tracker.m",
"//ui/webui/resources/js:list_property_update_behavior.m", "//ui/webui/resources/js:list_property_update_behavior.m",
"//ui/webui/resources/js:web_ui_listener_behavior.m",
] ]
} }
} else { } else {
......
<style include="destination-dialog"> <style include="destination-dialog">
.form-row {
align-items: center;
column-gap: 18px;
display: flex;
line-height: calc(20 / 15 * 1em);
margin-bottom: 14px;
}
.server-search-box-input {
--cr-searchable-drop-down-width: 100%;
display: inline-block;
flex-grow: 1;
}
</style> </style>
<cr-dialog id="dialog" on-close="onCloseOrCancel_"> <cr-dialog id="dialog" on-close="onCloseOrCancel_">
<div slot="title" id="header">$i18n{destinationSearchTitle}</div> <div slot="title" id="header">$i18n{destinationSearchTitle}</div>
<div slot="body"> <div slot="body">
<div class="user-info" hidden$="[[!activeUser]]" hidden> <div class="form-row">
<label id="accountSelectLabel">$i18n{accountSelectTitle}</label> <div class="user-info" hidden$="[[!activeUser]]" hidden>
<select class="md-select" <label id="accountSelectLabel">$i18n{accountSelectTitle}</label>
aria-labelledby="accountSelectLabel" on-change="onUserChange_"> <select class="md-select"
<template is="dom-repeat" items="[[users]]"> aria-labelledby="accountSelectLabel" on-change="onUserChange_">
<option value="[[item]]">[[item]]</option> <template is="dom-repeat" items="[[users]]">
</template> <option value="[[item]]">[[item]]</option>
<option value="">$i18n{addAccountTitle}</option> </template>
</select> <option value="">$i18n{addAccountTitle}</option>
</select>
</div>
<template is="dom-if" if="[[printServerScalingFlagEnabled_]]">
<!-- TODO(crbug.com/1013408): Uses deprecated iron-dropdown. -->
<cr-searchable-drop-down class="server-search-box-input"
hidden$="[[!isSingleServerFetchingMode_]]"
placeholder="$i18n{serverSearchBoxPlaceholder}"
value="{{printServerSelected_}}"
items="[[printServerNames_]]">
</cr-searchable-drop-down>
</template>
</div> </div>
<print-preview-search-box id="searchBox" <print-preview-search-box id="searchBox"
label="$i18n{searchBoxPlaceholder}" search-query="{{searchQuery_}}" label="$i18n{searchBoxPlaceholder}" search-query="{{searchQuery_}}"
...@@ -19,7 +43,7 @@ ...@@ -19,7 +43,7 @@
</print-preview-search-box> </print-preview-search-box>
<print-preview-destination-list id="printList" <print-preview-destination-list id="printList"
destinations="[[destinations_]]" destinations="[[destinations_]]"
loading-destinations="[[loadingDestinations_]]" loading-destinations="[[loadingAnyDestinations_]]"
search-query="[[searchQuery_]]" search-query="[[searchQuery_]]"
on-destination-selected="onDestinationSelected_"> on-destination-selected="onDestinationSelected_">
</print-preview-destination-list> </print-preview-destination-list>
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
import 'chrome://resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.m.js';
import 'chrome://resources/cr_elements/hidden_style_css.m.js'; import 'chrome://resources/cr_elements/hidden_style_css.m.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/js/action_link.js'; import 'chrome://resources/js/action_link.js';
...@@ -26,20 +27,26 @@ import {assert} from 'chrome://resources/js/assert.m.js'; ...@@ -26,20 +27,26 @@ import {assert} from 'chrome://resources/js/assert.m.js';
import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js';
import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js'; import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
import {beforeNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {beforeNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {Destination} from '../data/destination.js'; import {Destination} from '../data/destination.js';
import {DestinationStore} from '../data/destination_store.js'; import {DestinationStore} from '../data/destination_store.js';
import {InvitationStore} from '../data/invitation_store.js'; import {InvitationStore} from '../data/invitation_store.js';
import {PrintServerStore} from '../data/print_server_store.js';
import {Metrics, MetricsContext} from '../metrics.js'; import {Metrics, MetricsContext} from '../metrics.js';
import {NativeLayerImpl} from '../native_layer.js'; import {NativeLayerImpl} from '../native_layer.js';
import {PrintServer, PrintServersConfig} from '../native_layer_cros.js';
Polymer({ Polymer({
is: 'print-preview-destination-dialog-cros', is: 'print-preview-destination-dialog-cros',
_template: html`{__html_template__}`, _template: html`{__html_template__}`,
behaviors: [ListPropertyUpdateBehavior], behaviors: [
ListPropertyUpdateBehavior,
WebUIListenerBehavior,
],
properties: { properties: {
/** @type {?DestinationStore} */ /** @type {?DestinationStore} */
...@@ -61,6 +68,13 @@ Polymer({ ...@@ -61,6 +68,13 @@ Polymer({
/** @type {!Array<string>} */ /** @type {!Array<string>} */
users: Array, users: Array,
/** @private */
printServerSelected_: {
type: String,
value: '',
observer: 'onPrintServerSelected_',
},
/** @private {!Array<!Destination>} */ /** @private {!Array<!Destination>} */
destinations_: { destinations_: {
type: Array, type: Array,
...@@ -90,6 +104,42 @@ Polymer({ ...@@ -90,6 +104,42 @@ Polymer({
}, },
readOnly: true, readOnly: true,
}, },
/** @private {boolean} */
isSingleServerFetchingMode_: {
type: Boolean,
value: false,
},
/** @private {!Array<string>} */
printServerNames_: {
type: Array,
value() {
return [''];
},
},
/** @private */
printServerScalingFlagEnabled_: {
type: Boolean,
value() {
return loadTimeData.getBoolean('printServerScaling');
},
readOnly: true,
},
/** @private {boolean} */
loadingServerPrinters_: {
type: Boolean,
value: false,
},
/** @private {boolean} */
loadingAnyDestinations_: {
type: Boolean,
computed:
'computeLoadingDestinations_(loadingDestinations_, loadingServerPrinters_)'
},
}, },
listeners: { listeners: {
...@@ -105,11 +155,37 @@ Polymer({ ...@@ -105,11 +155,37 @@ Polymer({
/** @private {boolean} */ /** @private {boolean} */
initialized_: false, initialized_: false,
/** @private {?PrintServerStore} */
printServerStore_: null,
/** @override */ /** @override */
detached() { detached() {
this.tracker_.removeAll(); this.tracker_.removeAll();
}, },
/** @override */
ready() {
if (!this.printServerScalingFlagEnabled_) {
return;
}
this.printServerStore_ = new PrintServerStore(
(/** string */ eventName, /** !Function */ callback) =>
void this.addWebUIListener(eventName, callback));
this.tracker_.add(
this.printServerStore_,
PrintServerStore.EventType.PRINT_SERVERS_CHANGED,
event => void this.onPrintServersChanged_(event));
this.tracker_.add(
this.printServerStore_,
PrintServerStore.EventType.SERVER_PRINTERS_LOADING,
event => void this.onServerPrintersLoading_(event));
this.printServerStore_.getPrintServersConfig().then(config => {
this.printServerNames_ =
config.printServers.map(printServer => printServer.name);
this.isSingleServerFetchingMode_ = config.isSingleServerFetchingMode;
});
},
/** /**
* @param {!KeyboardEvent} e Event containing the key * @param {!KeyboardEvent} e Event containing the key
* @private * @private
...@@ -292,6 +368,45 @@ Polymer({ ...@@ -292,6 +368,45 @@ Polymer({
return this.$.dialog.hasAttribute('open'); return this.$.dialog.hasAttribute('open');
}, },
/**
* @param {string} printServerName The name of the print server.
* @private
*/
onPrintServerSelected_(printServerName) {
if (!this.printServerScalingFlagEnabled_ || !this.printServerStore_) {
return;
}
this.printServerStore_.choosePrintServers(printServerName);
},
/**
* @param {!CustomEvent<!{printServerNames: !Array<string>,
* isSingleServerFetchingMode: boolean}>} e Event containing the current
* print server names and fetching mode.
* @private
*/
onPrintServersChanged_(e) {
this.isSingleServerFetchingMode_ = e.detail.isSingleServerFetchingMode;
this.printServerNames_ = e.detail.printServerNames;
},
/**
* @param {!CustomEvent<boolean>} e Event containing whether server printers
* are currently loading.
* @private
*/
onServerPrintersLoading_(e) {
this.loadingServerPrinters_ = e.detail;
},
/**
* @return {boolean} Whether the destinations are loading.
* @private
*/
computeLoadingDestinations_() {
return this.loadingDestinations_ || this.loadingServerPrinters_;
},
/** @private */ /** @private */
onUserChange_() { onUserChange_() {
const select = this.$$('select'); const select = this.$$('select');
......
...@@ -313,6 +313,10 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) { ...@@ -313,6 +313,10 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) {
{"selectButton", IDS_PRINT_PREVIEW_BUTTON_SELECT}, {"selectButton", IDS_PRINT_PREVIEW_BUTTON_SELECT},
{"seeMore", IDS_PRINT_PREVIEW_SEE_MORE}, {"seeMore", IDS_PRINT_PREVIEW_SEE_MORE},
{"seeMoreDestinationsLabel", IDS_PRINT_PREVIEW_SEE_MORE_DESTINATIONS_LABEL}, {"seeMoreDestinationsLabel", IDS_PRINT_PREVIEW_SEE_MORE_DESTINATIONS_LABEL},
#if defined(OS_CHROMEOS)
{"serverSearchBoxPlaceholder",
IDS_PRINT_PREVIEW_SERVER_SEARCH_BOX_PLACEHOLDER},
#endif
{"title", IDS_PRINT_PREVIEW_TITLE}, {"title", IDS_PRINT_PREVIEW_TITLE},
{"top", IDS_PRINT_PREVIEW_TOP_MARGIN_LABEL}, {"top", IDS_PRINT_PREVIEW_TOP_MARGIN_LABEL},
{"unsupportedCloudPrinter", IDS_PRINT_PREVIEW_UNSUPPORTED_CLOUD_PRINTER}, {"unsupportedCloudPrinter", IDS_PRINT_PREVIEW_UNSUPPORTED_CLOUD_PRINTER},
...@@ -400,6 +404,9 @@ void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) { ...@@ -400,6 +404,9 @@ void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) {
source->AddBoolean( source->AddBoolean(
"printSaveToDrive", "printSaveToDrive",
base::FeatureList::IsEnabled(chromeos::features::kPrintSaveToDrive)); base::FeatureList::IsEnabled(chromeos::features::kPrintSaveToDrive));
source->AddBoolean(
"printServerScaling",
base::FeatureList::IsEnabled(chromeos::features::kPrintServerScaling));
#endif #endif
} }
...@@ -574,8 +581,7 @@ void PrintPreviewUI::ClearAllPreviewData() { ...@@ -574,8 +581,7 @@ void PrintPreviewUI::ClearAllPreviewData() {
PrintPreviewDataService::GetInstance()->RemoveEntry(*id_); PrintPreviewDataService::GetInstance()->RemoveEntry(*id_);
} }
void PrintPreviewUI::SetInitiatorTitle( void PrintPreviewUI::SetInitiatorTitle(const base::string16& job_title) {
const base::string16& job_title) {
initiator_title_ = job_title; initiator_title_ = job_title;
} }
......
...@@ -4,15 +4,16 @@ ...@@ -4,15 +4,16 @@
import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationType, InvitationStore, LocalDestinationInfo, makeRecentDestination, NativeLayerImpl, RecentDestination} from 'chrome://print/print_preview.js'; import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationType, InvitationStore, LocalDestinationInfo, makeRecentDestination, NativeLayerImpl, RecentDestination} from 'chrome://print/print_preview.js';
import {assert} from 'chrome://resources/js/assert.m.js'; import {assert} from 'chrome://resources/js/assert.m.js';
import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {keyEventOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; import {keyEventOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
import {eventToPromise} from '../test_util.m.js'; import {eventToPromise, waitAfterNextRender} from '../test_util.m.js';
import {CloudPrintInterfaceStub} from './cloud_print_interface_stub.js'; import {CloudPrintInterfaceStub} from './cloud_print_interface_stub.js';
import {setNativeLayerCrosInstance} from './native_layer_cros_stub.js'; import {NativeLayerCrosStub, setNativeLayerCrosInstance} from './native_layer_cros_stub.js';
import {NativeLayerStub} from './native_layer_stub.js'; import {NativeLayerStub} from './native_layer_stub.js';
import {createDestinationStore, getDestinations, getGoogleDriveDestination, setupTestListenerElement} from './print_preview_test_utils.js'; import {createDestinationStore, getDestinations, getGoogleDriveDestination, setupTestListenerElement} from './print_preview_test_utils.js';
...@@ -24,6 +25,8 @@ destination_dialog_cros_test.TestNames = { ...@@ -24,6 +25,8 @@ destination_dialog_cros_test.TestNames = {
PrinterList: 'PrinterList', PrinterList: 'PrinterList',
ShowProvisionalDialog: 'ShowProvisionalDialog', ShowProvisionalDialog: 'ShowProvisionalDialog',
UserAccounts: 'UserAccounts', UserAccounts: 'UserAccounts',
PrintServersChanged: 'PrintServersChanged',
PrintServerSelected: 'PrintServerSelected',
}; };
suite(destination_dialog_cros_test.suiteName, function() { suite(destination_dialog_cros_test.suiteName, function() {
...@@ -36,6 +39,9 @@ suite(destination_dialog_cros_test.suiteName, function() { ...@@ -36,6 +39,9 @@ suite(destination_dialog_cros_test.suiteName, function() {
/** @type {!NativeLayerStub} */ /** @type {!NativeLayerStub} */
let nativeLayer; let nativeLayer;
/** @type {!NativeLayerCrosStub} */
let nativeLayerCros;
/** @type {!CloudPrintInterfaceStub} */ /** @type {!CloudPrintInterfaceStub} */
let cloudPrintInterface; let cloudPrintInterface;
...@@ -61,7 +67,7 @@ suite(destination_dialog_cros_test.suiteName, function() { ...@@ -61,7 +67,7 @@ suite(destination_dialog_cros_test.suiteName, function() {
// Create data classes // Create data classes
nativeLayer = new NativeLayerStub(); nativeLayer = new NativeLayerStub();
NativeLayerImpl.instance_ = nativeLayer; NativeLayerImpl.instance_ = nativeLayer;
setNativeLayerCrosInstance(); nativeLayerCros = setNativeLayerCrosInstance();
cloudPrintInterface = new CloudPrintInterfaceStub(); cloudPrintInterface = new CloudPrintInterfaceStub();
destinationStore = createDestinationStore(); destinationStore = createDestinationStore();
destinationStore.setCloudPrintInterface(cloudPrintInterface); destinationStore.setCloudPrintInterface(cloudPrintInterface);
...@@ -306,4 +312,61 @@ suite(destination_dialog_cros_test.suiteName, function() { ...@@ -306,4 +312,61 @@ suite(destination_dialog_cros_test.suiteName, function() {
// Cloud print should have been queried again for the new account. // Cloud print should have been queried again for the new account.
assertEquals(3, cloudPrintInterface.getCallCount('search')); assertEquals(3, cloudPrintInterface.getCallCount('search'));
}); });
// Test that checks that print server searchable input and its selections are
// updated according to the PRINT_SERVERS_CHANGED event.
test(
assert(destination_dialog_cros_test.TestNames.PrintServersChanged),
async () => {
await finishSetup();
const printServers = [
{id: 'print-server-1', name: 'Print Server 1'},
{id: 'print-server-2', name: 'Print Server 2'},
];
const isSingleServerFetchingMode = true;
webUIListenerCallback('print-servers-config-changed', {
printServers: printServers,
isSingleServerFetchingMode: isSingleServerFetchingMode,
});
await waitAfterNextRender(dialog);
assertFalse(dialog.$$('.server-search-box-input').hidden);
const serverSelector = dialog.$$('.server-search-box-input');
const serverSelections =
serverSelector.shadowRoot.querySelectorAll('.list-item');
assertEquals('Print Server 1', serverSelections[0].textContent.trim());
assertEquals('Print Server 2', serverSelections[1].textContent.trim());
});
// Tests that choosePrintServers is called when the print server searchable
// input value is changed.
test(
assert(destination_dialog_cros_test.TestNames.PrintServerSelected),
async () => {
await finishSetup();
const printServers = [
{id: 'user-print-server-1', name: 'Print Server 1'},
{id: 'user-print-server-2', name: 'Print Server 2'},
{id: 'device-print-server-1', name: 'Print Server 1'},
{id: 'device-print-server-2', name: 'Print Server 2'},
];
const isSingleServerFetchingMode = true;
webUIListenerCallback('print-servers-config-changed', {
printServers: printServers,
isSingleServerFetchingMode: isSingleServerFetchingMode,
});
await waitAfterNextRender(dialog);
nativeLayerCros.reset();
const pendingPrintServerId =
nativeLayerCros.whenCalled('choosePrintServers');
dialog.$$('cr-searchable-drop-down').value = 'Print Server 2';
await waitAfterNextRender(dialog);
assertEquals(1, nativeLayerCros.getCallCount('choosePrintServers'));
assertDeepEquals(
['user-print-server-2', 'device-print-server-2'],
await pendingPrintServerId);
});
}); });
...@@ -726,6 +726,16 @@ var PrintPreviewDestinationDialogCrosTest = class extends PrintPreviewTest { ...@@ -726,6 +726,16 @@ var PrintPreviewDestinationDialogCrosTest = class extends PrintPreviewTest {
get suiteName() { get suiteName() {
return destination_dialog_cros_test.suiteName; return destination_dialog_cros_test.suiteName;
} }
/** @override */
get featureList() {
const featureList = super.featureList || [];
const kPrintServerScaling = ['chromeos::features::kPrintServerScaling'];
featureList.enabled = featureList.enabled ?
featureList.enabled.concat(kPrintServerScaling) :
kPrintServerScaling;
return featureList;
}
}; };
TEST_F('PrintPreviewDestinationDialogCrosTest', 'PrinterList', function() { TEST_F('PrintPreviewDestinationDialogCrosTest', 'PrinterList', function() {
...@@ -743,6 +753,18 @@ TEST_F('PrintPreviewDestinationDialogCrosTest', 'UserAccounts', function() { ...@@ -743,6 +753,18 @@ TEST_F('PrintPreviewDestinationDialogCrosTest', 'UserAccounts', function() {
this.runMochaTest(destination_dialog_cros_test.TestNames.UserAccounts); this.runMochaTest(destination_dialog_cros_test.TestNames.UserAccounts);
}); });
TEST_F(
'PrintPreviewDestinationDialogCrosTest', 'PrintServersChanged', function() {
this.runMochaTest(
destination_dialog_cros_test.TestNames.PrintServersChanged);
});
TEST_F(
'PrintPreviewDestinationDialogCrosTest', 'PrintServerSelected', function() {
this.runMochaTest(
destination_dialog_cros_test.TestNames.PrintServerSelected);
});
GEN('#endif'); GEN('#endif');
// eslint-disable-next-line no-var // eslint-disable-next-line no-var
......
...@@ -80,7 +80,7 @@ suite(print_server_store_test.suiteName, function() { ...@@ -80,7 +80,7 @@ suite(print_server_store_test.suiteName, function() {
async () => { async () => {
const printServers = [ const printServers = [
{id: 'server1', name: 'Print Server 1'}, {id: 'server1', name: 'Print Server 1'},
{id: 'server2', name: 'Print Server 2'} {id: 'server2', name: 'Print Server 2'},
]; ];
const whenPrintServersChangedEvent = eventToPromise( const whenPrintServersChangedEvent = eventToPromise(
PrintServerStore.EventType.PRINT_SERVERS_CHANGED, printServerStore); PrintServerStore.EventType.PRINT_SERVERS_CHANGED, printServerStore);
......
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