Commit 37d98c47 authored by Devlin Cronin's avatar Devlin Cronin Committed by Commit Bot

[Extensions Click-to-Script] Pull out runtime host permissions element

Create a custom element for the runtime host permissions controls in
the chrome://extensions page, rather than having them defined in the
DetailView element. This will make it easier to test and expand the
controls.

Pull the controls into runtime_host_permissions.[js|html], and extract
the tests from extension_detail_view_test.js to
extension_runtime_host_permisisons_test.js. Also add an additional test
to verify the runtime host permissions dialog is shown when the 'add'
button is clicked.

There should be no visible UI changes as a result of this CL.

Bug: 844128
Change-Id: I741adc921af95253087dbf31be1800c01fb4185c
Reviewed-on: https://chromium-review.googlesource.com/1146999Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577367}
parent 32d2b4e3
......@@ -68,6 +68,7 @@ js_type_check("closure_compile") {
":options_dialog",
":pack_dialog",
":pack_dialog_alert",
":runtime_host_permissions",
":runtime_hosts_dialog",
":service",
":shortcut_input",
......@@ -280,6 +281,14 @@ js_library("pack_dialog_alert") {
externs_list = [ "$externs_path/developer_private.js" ]
}
js_library("runtime_host_permissions") {
deps = [
":item",
":runtime_hosts_dialog",
]
externs_list = [ "$externs_path/developer_private.js" ]
}
js_library("runtime_hosts_dialog") {
deps = [
"//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
......
......@@ -13,22 +13,21 @@
<link rel="import" href="chrome://resources/html/action_link_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<link rel="import" href="runtime_hosts_dialog.html">
<link rel="import" href="item_behavior.html">
<link rel="import" href="item_util.html">
<link rel="import" href="navigation_helper.html">
<link rel="import" href="runtime_host_permissions.html">
<link rel="import" href="strings.html">
<link rel="import" href="toggle_row.html">
<dom-module id="extensions-detail-view">
<template>
<style include="iron-flex cr-shared-style cr-icons action-link md-select paper-button-style">
<style include="iron-flex cr-shared-style cr-icons action-link paper-button-style">
:host {
--iron-icon-fill-color: var(--google-grey-refresh-700);
display: block;
......@@ -125,18 +124,6 @@
color: var(--cr-secondary-text-color);
}
#add-runtime-hosts-section {
align-items: center;
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.mid-section-header {
color: var(--cr-primary-text-color);
margin-top: 12px;
}
.actionable {
cursor: pointer;
}
......@@ -174,12 +161,6 @@
margin: 0;
}
#runtime-host-permissions-mode {
align-items: center;
display: flex;
justify-content: space-between;
}
#options-section .control-line:first-child {
border-top: var(--cr-separator-line);
}
......@@ -348,43 +329,11 @@
</template>
</ul>
<template is="dom-if" if="[[showRuntimeHostPermissions_(data.*)]]">
<div id="runtime-host-permissions">
<div id="runtime-host-permissions-mode">
<div class="mid-section-header">
$i18n{itemHostPermissionsHeading}
</div>
<select id="host-access" class="md-select"
value="[[data.permissions.hostAccess]]"
on-change="onHostAccessChanged_">
<option value$="[[HostAccess_.ON_CLICK]]">
$i18n{itemHostAccessOnClick}
</option>
<option value$="[[HostAccess_.ON_SPECIFIC_SITES]]">
$i18n{itemHostAccessOnSpecificSites}
</option>
<option value$="[[HostAccess_.ON_ALL_SITES]]">
$i18n{itemHostAccessOnAllSites}
</option>
</select>
</div>
<template is="dom-if" if="[[showSpecificSites_(data.*)]]">
<div id="add-runtime-hosts-section">
<div class="mid-section-header">
$i18n{itemAllowedHosts}
</div>
<paper-button id="add-runtime-host"
on-click="onAddRuntimeHostClick_">
$i18n{add}
</paper-button>
</div>
<ul id="runtime-hosts">
<template is="dom-repeat"
items="[[data.permissions.runtimeHostPermissions]]">
<li>[[item]]</li>
</template>
</ul>
</template>
</div>
<extensions-runtime-host-permissions
permissions="[[data.permissions]]"
delegate="[[delegate]]"
item-id="[[data.id]]">
</extensions-runtime-host-permissions>
</template>
</div>
</div>
......@@ -465,12 +414,6 @@
</cr-link-row>
</div>
</div>
<template is="dom-if" if="[[showRuntimeHostsDialog_]]" restamp>
<extensions-runtime-hosts-dialog
delegate="[[delegate]]" item-id="[[data.id]]"
on-close="onRuntimeHostsDialogClosed_">
</extensions-runtime-hosts-dialog>
</template>
</template>
<script src="detail_view.js"></script>
</dom-module>
......@@ -31,21 +31,6 @@ cr.define('extensions', function() {
/** Whether "allow in incognito" option should be shown. */
incognitoAvailable: Boolean,
/**
* Whether the dialog to add a new host permission is shown.
* @private
*/
showRuntimeHostsDialog_: Boolean,
/**
* Proxying the enum to be used easily by the html template.
* @private
*/
HostAccess_: {
type: Object,
value: chrome.developerPrivate.HostAccess,
},
},
observers: [
......@@ -90,22 +75,6 @@ cr.define('extensions', function() {
extensions.navigation.navigateTo({page: Page.LIST});
},
/**
* @param {!Event} event
* @private
*/
onHostAccessChanged_: function(event) {
const select = /** @type {!HTMLSelectElement} */ (event.target);
const access =
/** @type {chrome.developerPrivate.HostAccess} */ (select.value);
this.delegate.setItemHostAccess(this.data.id, access);
// Force the UI to update (in order to potentially hide or show the
// specific runtime hosts).
// TODO(devlin): Perhaps this should be handled by the backend updating
// and sending an onItemStateChanged event?
this.set('data.permissions.hostAccess', access);
},
/**
* @return {boolean}
* @private
......@@ -324,27 +293,6 @@ cr.define('extensions', function() {
showRuntimeHostPermissions_: function() {
return !!this.data.permissions.hostAccess;
},
/**
* @return {boolean}
* @private
*/
showSpecificSites_: function() {
return this.data.permissions &&
this.data.permissions.hostAccess ==
chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES;
},
/** @private */
onAddRuntimeHostClick_: function() {
this.showRuntimeHostsDialog_ = true;
},
/** @private */
onRuntimeHostsDialogClosed_: function() {
this.showRuntimeHostsDialog_ = false;
cr.ui.focusWithoutInk(assert(this.$$('#add-runtime-host')));
},
});
return {DetailView: DetailView};
......
......@@ -141,6 +141,12 @@
<structure name="IDR_MD_EXTENSIONS_PACK_DIALOG_ALERT_JS"
file="pack_dialog_alert.js"
type="chrome_html" />
<structure name="IDR_MD_EXTENSIONS_RUNTIME_HOST_PERMISSIONS_HMTL"
file="runtime_host_permissions.html"
type="chrome_html" />
<structure name="IDR_MD_EXTENSIONS_RUNTIME_HOST_PERMISSIONS_JS"
file="runtime_host_permissions.js"
type="chrome_html" />
<structure name="IDR_MD_EXTENSIONS_RUNTIME_HOSTS_DIALOG_HTML"
file="runtime_hosts_dialog.html"
type="chrome_html" />
......
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="runtime_hosts_dialog.html">
<link rel="import" href="strings.html">
<dom-module id="extensions-runtime-host-permissions">
<template>
<style include="cr-shared-style md-select paper-button-style">
#add-hosts-section {
align-items: center;
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.mid-section-header {
color: var(--cr-primary-text-color);
margin-top: 12px;
}
#permissions-mode {
align-items: center;
display: flex;
justify-content: space-between;
}
</style>
<div id="permissions-mode">
<div class="mid-section-header">
$i18n{hostPermissionsHeading}
</div>
<select id="host-access" class="md-select"
value="[[permissions.hostAccess]]"
on-change="onHostAccessChange_">
<option value$="[[HostAccess_.ON_CLICK]]">
$i18n{hostAccessOnClick}
</option>
<option value$="[[HostAccess_.ON_SPECIFIC_SITES]]">
$i18n{hostAccessOnSpecificSites}
</option>
<option value$="[[HostAccess_.ON_ALL_SITES]]">
$i18n{hostAccessOnAllSites}
</option>
</select>
</div>
<template is="dom-if" if="[[showSpecificSites_(permissions.*)]]">
<div id="add-hosts-section">
<div class="mid-section-header">
$i18n{hostAllowedHosts}
</div>
<paper-button id="add-host" on-click="onAddHostClick_">
$i18n{add}
</paper-button>
</div>
<ul id="hosts">
<template is="dom-repeat"
items="[[permissions.runtimeHostPermissions]]">
<li>[[item]]</li>
</template>
</ul>
</template>
<template is="dom-if" if="[[showHostsDialog_]]" restamp>
<extensions-runtime-hosts-dialog
delegate="[[delegate]]" item-id="[[itemId]]"
on-close="onHostsDialogClosed_">
</extensions-runtime-hosts-dialog>
</template>
</template>
<script src="runtime_host_permissions.js"></script>
</dom-module>
// Copyright 2018 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.
cr.define('extensions', function() {
'use strict';
const RuntimeHostPermissions = Polymer({
is: 'extensions-runtime-host-permissions',
properties: {
/**
* The underlying permissions data.
* @type {chrome.developerPrivate.Permissions}
*/
permissions: Object,
/** @private */
itemId: String,
/** @type {!extensions.ItemDelegate} */
delegate: Object,
/**
* Whether the dialog to add a new host permission is shown.
* @private
*/
showHostsDialog_: Boolean,
/**
* Proxying the enum to be used easily by the html template.
* @private
*/
HostAccess_: {
type: Object,
value: chrome.developerPrivate.HostAccess,
},
},
/**
* @param {!Event} event
* @private
*/
onHostAccessChange_: function(event) {
const select = /** @type {!HTMLSelectElement} */ (event.target);
const access =
/** @type {chrome.developerPrivate.HostAccess} */ (select.value);
this.delegate.setItemHostAccess(this.itemId, access);
// Force the UI to update (in order to potentially hide or show the
// specific runtime hosts).
// TODO(devlin): Perhaps this should be handled by the backend updating
// and sending an onItemStateChanged event?
this.set('permissions.hostAccess', access);
},
/**
* @return {boolean}
* @private
*/
showSpecificSites_: function() {
return this.permissions &&
this.permissions.hostAccess ==
chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES;
},
/** @private */
onAddHostClick_: function() {
this.showHostsDialog_ = true;
},
/** @private */
onHostsDialogClosed_: function() {
this.showHostsDialog_ = false;
cr.ui.focusWithoutInk(assert(this.$$('#add-host')));
},
});
return {RuntimeHostPermissions: RuntimeHostPermissions};
});
......@@ -158,13 +158,12 @@ content::WebUIDataSource* CreateMdExtensionsSource(bool in_dev_mode) {
{"openChromeWebStore", IDS_MD_EXTENSIONS_SIDEBAR_OPEN_CHROME_WEB_STORE},
{"keyboardShortcuts", IDS_MD_EXTENSIONS_SIDEBAR_KEYBOARD_SHORTCUTS},
{"incognitoInfoWarning", IDS_EXTENSIONS_INCOGNITO_WARNING},
{"itemHostPermissionsHeading",
IDS_MD_EXTENSIONS_ITEM_HOST_PERMISSIONS_HEADING},
{"itemHostAccessOnClick", IDS_MD_EXTENSIONS_HOST_ACCESS_ON_CLICK},
{"itemHostAccessOnSpecificSites",
{"hostPermissionsHeading", IDS_MD_EXTENSIONS_ITEM_HOST_PERMISSIONS_HEADING},
{"hostAccessOnClick", IDS_MD_EXTENSIONS_HOST_ACCESS_ON_CLICK},
{"hostAccessOnSpecificSites",
IDS_MD_EXTENSIONS_HOST_ACCESS_ON_SPECIFIC_SITES},
{"itemHostAccessOnAllSites", IDS_MD_EXTENSIONS_HOST_ACCESS_ON_ALL_SITES},
{"itemAllowedHosts", IDS_EXTENSIONS_ITEM_ALLOWED_HOSTS},
{"hostAccessOnAllSites", IDS_MD_EXTENSIONS_HOST_ACCESS_ON_ALL_SITES},
{"hostAllowedHosts", IDS_EXTENSIONS_ITEM_ALLOWED_HOSTS},
{"itemId", IDS_MD_EXTENSIONS_ITEM_ID},
{"itemInspectViews", IDS_MD_EXTENSIONS_ITEM_INSPECT_VIEWS},
// NOTE: This text reads "<n> more". It's possible that it should be using
......
......@@ -232,19 +232,6 @@ TEST_F('CrExtensionsDetailViewTest', 'Warnings', function() {
this.runMochaTest(extension_detail_view_tests.TestNames.Warnings);
});
TEST_F(
'CrExtensionsDetailViewTest', 'RuntimeHostPermissionsDisplay', function() {
this.runMochaTest(
extension_detail_view_tests.TestNames.RuntimeHostPermissionsDisplay);
});
TEST_F(
'CrExtensionsDetailViewTest', 'RuntimeHostPermissionsSelection',
function() {
this.runMochaTest(extension_detail_view_tests.TestNames
.RuntimeHostPermissionsSelection);
});
////////////////////////////////////////////////////////////////////////////////
// Extension Item List Tests
......@@ -855,3 +842,23 @@ CrExtensionsRuntimeHostsDialogTest = class extends CrExtensionsBrowserTest {
TEST_F('CrExtensionsRuntimeHostsDialogTest', 'All', () => {
mocha.run();
});
////////////////////////////////////////////////////////////////////////////////
// RuntimeHostPermissions tests
CrExtensionsRuntimeHostPermissionsTest = class extends CrExtensionsBrowserTest {
/** @override */
get browserPreload() {
return 'chrome://extensions/runtime_host_permissions.html';
}
get extraLibraries() {
return super.extraLibraries.concat([
'extension_runtime_host_permissions_test.js',
]);
}
};
TEST_F('CrExtensionsRuntimeHostPermissionsTest', 'All', () => {
mocha.run();
});
......@@ -11,8 +11,6 @@ cr.define('extension_detail_view_tests', function() {
ClickableElements: 'clickable elements',
Indicator: 'indicator',
Warnings: 'warnings',
RuntimeHostPermissionsDisplay: 'runtime host permissions display',
RuntimeHostPermissionsSelection: 'runtime host permissions selection',
};
const suiteName = 'ExtensionDetailViewTest';
......@@ -98,7 +96,7 @@ cr.define('extension_detail_view_tests', function() {
expectFalse(testIsVisible('#permissions-list'));
expectFalse(testIsVisible('#host-access'));
expectFalse(testIsVisible('#runtime-hosts'));
expectFalse(testIsVisible('extensions-runtime-host-permissions'));
expectTrue(testIsVisible('#no-permissions'));
item.set(
......@@ -110,7 +108,7 @@ cr.define('extension_detail_view_tests', function() {
2, item.$$('#permissions-list').querySelectorAll('li').length);
expectFalse(testIsVisible('#no-permissions'));
expectFalse(testIsVisible('#host-access'));
expectFalse(testIsVisible('#runtime-hosts'));
expectFalse(testIsVisible('extensions-runtime-host-permissions'));
const optionsUrl =
'chrome-extension://' + extensionData.id + '/options.html';
......@@ -160,6 +158,14 @@ cr.define('extension_detail_view_tests', function() {
item.set('data.runtimeWarnings', ['Dummy warning']);
Polymer.dom.flush();
expectTrue(testIsVisible('.warning-icon'));
// Adding any runtime host permissions should result in the runtime host
// controls becoming visible.
item.set(
'data.permissions.hostAccess',
chrome.developerPrivate.HostAccess.ON_CLICK);
Polymer.dom.flush();
expectTrue(testIsVisible('extensions-runtime-host-permissions'));
});
test(assert(TestNames.LayoutSource), function() {
......@@ -297,81 +303,6 @@ cr.define('extension_detail_view_tests', function() {
testWarningVisible('#blacklisted-warning', false);
testWarningVisible('#update-required-warning', false);
});
test(assert(TestNames.RuntimeHostPermissionsDisplay), function() {
const HostAccess = chrome.developerPrivate.HostAccess;
const permissions = {
simplePermissions: ['permission 1', 'permission 2'],
hostAccess: HostAccess.ON_CLICK,
runtimeHostPermissions: [],
};
item.set('data.permissions', permissions);
Polymer.dom.flush();
const testIsVisible = extension_test_util.isVisible.bind(null, item);
expectTrue(testIsVisible('#host-access'));
// The host-access menu should be visible, since the data includes
// host access information.
const selectHostAccess = item.$$('#host-access');
expectEquals(HostAccess.ON_CLICK, selectHostAccess.value);
// For on-click mode, there should be no runtime hosts listed.
expectFalse(testIsVisible('#runtime-hosts'));
// Changing the data's access should change the UI appropriately.
item.set('data.permissions.hostAccess', HostAccess.ON_ALL_SITES);
Polymer.dom.flush();
expectEquals(HostAccess.ON_ALL_SITES, selectHostAccess.value);
expectFalse(testIsVisible('#runtime-hosts'));
// Setting the mode to on specific sites should display the runtime hosts
// list.
item.set('data.permissions.hostAccess', HostAccess.ON_SPECIFIC_SITES);
item.set(
'data.permissions.runtimeHostPermissions',
['https://example.com', 'https://chromium.org']);
Polymer.dom.flush();
expectEquals(HostAccess.ON_SPECIFIC_SITES, selectHostAccess.value);
expectTrue(testIsVisible('#runtime-hosts'));
expectEquals(
2, item.$$('#runtime-hosts').getElementsByTagName('li').length);
});
test(assert(TestNames.RuntimeHostPermissionsSelection), function() {
const HostAccess = chrome.developerPrivate.HostAccess;
const permissions = {
simplePermissions: ['permission 1', 'permission 2'],
hostAccess: HostAccess.ON_CLICK,
runtimeHostPermissions: [],
};
item.set('data.permissions', permissions);
Polymer.dom.flush();
const selectHostAccess = item.$$('#host-access');
// Changes the value of the selectHostAccess menu and fires the change
// event, then verifies that the delegate was called with the correct
// value.
function expectDelegateCallOnAccessChange(newValue) {
const mock = new MockController();
const mockMethod =
mock.createFunctionMock(mockDelegate, 'setItemHostAccess');
mockMethod.addExpectation(extensionData.id, newValue);
selectHostAccess.value = newValue;
selectHostAccess.dispatchEvent(
new CustomEvent('change', {target: selectHostAccess}));
mock.verifyMocks();
}
// Check that selecting different values correctly notifies the delegate.
expectDelegateCallOnAccessChange(HostAccess.ON_SPECIFIC_SITES);
expectDelegateCallOnAccessChange(HostAccess.ON_ALL_SITES);
expectDelegateCallOnAccessChange(HostAccess.ON_CLICK);
});
});
return {
......
// Copyright 2018 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.
suite('RuntimeHostPermissions', function() {
/** @type {extensions.RuntimeHostPermissionsElement} */ let element;
/** @type {extensions.TestService} */ let delegate;
const HostAccess = chrome.developerPrivate.HostAccess;
const ITEM_ID = 'a'.repeat(32);
setup(function() {
PolymerTest.clearBody();
element = document.createElement('extensions-runtime-host-permissions');
delegate = new extensions.TestService();
element.delegate = delegate;
element.itemId = ITEM_ID;
document.body.appendChild(element);
});
teardown(function() {
element.remove();
});
test('permissions display', function() {
const permissions = {
simplePermissions: ['permission 1', 'permission 2'],
hostAccess: HostAccess.ON_CLICK,
runtimeHostPermissions: [],
};
element.set('permissions', permissions);
Polymer.dom.flush();
const testIsVisible = extension_test_util.isVisible.bind(null, element);
expectTrue(testIsVisible('#host-access'));
const selectHostAccess = element.$$('#host-access');
expectEquals(HostAccess.ON_CLICK, selectHostAccess.value);
// For on-click mode, there should be no runtime hosts listed.
expectFalse(testIsVisible('#hosts'));
expectFalse(testIsVisible('#add-hosts-section'));
// Changing the data's access should change the UI appropriately.
element.set('permissions.hostAccess', HostAccess.ON_ALL_SITES);
Polymer.dom.flush();
expectEquals(HostAccess.ON_ALL_SITES, selectHostAccess.value);
expectFalse(testIsVisible('#hosts'));
expectFalse(testIsVisible('#add-hosts-section'));
// Setting the mode to on specific sites should display the runtime hosts
// list.
element.set('permissions.hostAccess', HostAccess.ON_SPECIFIC_SITES);
element.set(
'permissions.runtimeHostPermissions',
['https://example.com', 'https://chromium.org']);
Polymer.dom.flush();
expectEquals(HostAccess.ON_SPECIFIC_SITES, selectHostAccess.value);
expectTrue(testIsVisible('#hosts'));
expectTrue(testIsVisible('#add-hosts-section'));
expectEquals(2, element.$$('#hosts').getElementsByTagName('li').length);
});
test('permissions selection', function() {
const permissions = {
simplePermissions: ['permission 1', 'permission 2'],
hostAccess: HostAccess.ON_CLICK,
runtimeHostPermissions: [],
};
element.set('permissions', permissions);
Polymer.dom.flush();
const selectHostAccess = element.$$('#host-access');
assertTrue(!!selectHostAccess);
// Changes the value of the selectHostAccess menu and fires the change
// event, then verifies that the delegate was called with the correct
// value.
function expectDelegateCallOnAccessChange(newValue) {
selectHostAccess.value = newValue;
selectHostAccess.dispatchEvent(
new CustomEvent('change', {target: selectHostAccess}));
return delegate.whenCalled('setItemHostAccess').then((args) => {
expectEquals(ITEM_ID, args[0] /* id */);
expectEquals(newValue, args[1] /* access */);
delegate.resetResolver('setItemHostAccess');
});
}
// Check that selecting different values correctly notifies the delegate.
return expectDelegateCallOnAccessChange(HostAccess.ON_SPECIFIC_SITES)
.then(() => {
return expectDelegateCallOnAccessChange(HostAccess.ON_ALL_SITES);
})
.then(() => {
return expectDelegateCallOnAccessChange(HostAccess.ON_CLICK);
});
});
test('clicking add host triggers dialog', function() {
const permissions = {
simplePermissions: [],
hostAccess: HostAccess.ON_SPECIFIC_SITES,
runtimeHostPermissions: ['http://www.example.com'],
};
element.set('permissions', permissions);
Polymer.dom.flush();
const addHostButton = element.$$('#add-host');
assertTrue(!!addHostButton);
expectTrue(extension_test_util.isVisible(element, '#add-host'));
addHostButton.click();
Polymer.dom.flush();
const dialog = element.$$('extensions-runtime-hosts-dialog');
assertTrue(!!dialog);
expectTrue(dialog.$.dialog.open);
});
});
......@@ -14,6 +14,7 @@ cr.define('extensions', function() {
'loadUnpacked',
'retryLoadUnpacked',
'reloadItem',
'setItemHostAccess',
'setProfileInDevMode',
'setShortcutHandlingSuspended',
'shouldIgnoreUpdate',
......@@ -84,6 +85,11 @@ cr.define('extensions', function() {
return Promise.resolve('20 MB');
}
/** @override */
setItemHostAccess(id, access) {
this.methodCalled('setItemHostAccess', [id, access]);
}
/** @override */
setShortcutHandlingSuspended(enable) {
this.methodCalled('setShortcutHandlingSuspended', enable);
......
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