зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1283453 - Add network throttling UI to RDM. r=gl
MozReview-Commit-ID: 9MYLXuhlT2F
This commit is contained in:
Родитель
6de59d91bf
Коммит
a562ac8058
|
@ -58,3 +58,9 @@ responsive.screenshotGeneratedFilename=Screen Shot %1$S at %2$S
|
|||
# notification box if a user tries to open Responsive Design Mode in a
|
||||
# non-remote tab.
|
||||
responsive.remoteOnly=Responsive Design Mode is only available for remote browser tabs, such as those used for web content in multi-process Firefox.
|
||||
|
||||
# LOCALIZATION NOTE (responsive.noThrottling): UI option in a menu to configure
|
||||
# network throttling. This option is the default and disables throttling so you
|
||||
# just have normal network conditions. There is not very much room in the UI
|
||||
# so a short string would be best if possible.
|
||||
responsive.noThrottling=No throttling
|
||||
|
|
|
@ -24,10 +24,22 @@ createEnum([
|
|||
// Change the device displayed in the viewport.
|
||||
"CHANGE_DEVICE",
|
||||
|
||||
// The location of the page has changed. This may be triggered by the user
|
||||
// Change the location of the page. This may be triggered by the user
|
||||
// directly entering a new URL, navigating with links, etc.
|
||||
"CHANGE_LOCATION",
|
||||
|
||||
// Change the network throttling profile.
|
||||
"CHANGE_NETWORK_THROTTLING",
|
||||
|
||||
// Indicates that the device list is being loaded
|
||||
"LOAD_DEVICE_LIST_START",
|
||||
|
||||
// Indicates that the device list loading action threw an error
|
||||
"LOAD_DEVICE_LIST_ERROR",
|
||||
|
||||
// Indicates that the device list has been loaded successfully
|
||||
"LOAD_DEVICE_LIST_END",
|
||||
|
||||
// Resize the viewport.
|
||||
"RESIZE_VIEWPORT",
|
||||
|
||||
|
@ -43,15 +55,6 @@ createEnum([
|
|||
// Update the device display state in the device selector.
|
||||
"UPDATE_DEVICE_DISPLAYED",
|
||||
|
||||
// Indicates that the device list is being loaded
|
||||
"LOAD_DEVICE_LIST_START",
|
||||
|
||||
// Indicates that the device list loading action threw an error
|
||||
"LOAD_DEVICE_LIST_ERROR",
|
||||
|
||||
// Indicates that the device list has been loaded successfully
|
||||
"LOAD_DEVICE_LIST_END",
|
||||
|
||||
// Update the device modal open state.
|
||||
"UPDATE_DEVICE_MODAL_OPEN",
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ DevToolsModules(
|
|||
'devices.js',
|
||||
'index.js',
|
||||
'location.js',
|
||||
'network-throttling.js',
|
||||
'screenshot.js',
|
||||
'touch-simulation.js',
|
||||
'viewports.js',
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
CHANGE_NETWORK_THROTTLING,
|
||||
} = require("./index");
|
||||
|
||||
module.exports = {
|
||||
|
||||
changeNetworkThrottling(enabled, profile) {
|
||||
return {
|
||||
type: CHANGE_NETWORK_THROTTLING,
|
||||
enabled,
|
||||
profile,
|
||||
};
|
||||
},
|
||||
|
||||
};
|
|
@ -15,13 +15,14 @@ const {
|
|||
updateDeviceModalOpen,
|
||||
updatePreferredDevices,
|
||||
} = require("./actions/devices");
|
||||
const { changeNetworkThrottling } = require("./actions/network-throttling");
|
||||
const { takeScreenshot } = require("./actions/screenshot");
|
||||
const { updateTouchSimulationEnabled } = require("./actions/touch-simulation");
|
||||
const {
|
||||
changeDevice,
|
||||
resizeViewport,
|
||||
rotateViewport
|
||||
} = require("./actions/viewports");
|
||||
const { takeScreenshot } = require("./actions/screenshot");
|
||||
const { updateTouchSimulationEnabled } = require("./actions/touch-simulation");
|
||||
const DeviceModal = createFactory(require("./components/device-modal"));
|
||||
const GlobalToolbar = createFactory(require("./components/global-toolbar"));
|
||||
const Viewports = createFactory(require("./components/viewports"));
|
||||
|
@ -33,6 +34,7 @@ let App = createClass({
|
|||
propTypes: {
|
||||
devices: PropTypes.shape(Types.devices).isRequired,
|
||||
location: Types.location.isRequired,
|
||||
networkThrottling: PropTypes.shape(Types.networkThrottling).isRequired,
|
||||
screenshot: PropTypes.shape(Types.screenshot).isRequired,
|
||||
touchSimulation: PropTypes.shape(Types.touchSimulation).isRequired,
|
||||
viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
|
||||
|
@ -42,6 +44,15 @@ let App = createClass({
|
|||
window.postMessage({ type: "browser-mounted" }, "*");
|
||||
},
|
||||
|
||||
onChangeNetworkThrottling(enabled, profile) {
|
||||
window.postMessage({
|
||||
type: "change-network-throtting",
|
||||
enabled,
|
||||
profile,
|
||||
}, "*");
|
||||
this.props.dispatch(changeNetworkThrottling(enabled, profile));
|
||||
},
|
||||
|
||||
onChangeViewportDevice(id, device) {
|
||||
window.postMessage({
|
||||
type: "change-viewport-device",
|
||||
|
@ -100,6 +111,7 @@ let App = createClass({
|
|||
let {
|
||||
devices,
|
||||
location,
|
||||
networkThrottling,
|
||||
screenshot,
|
||||
touchSimulation,
|
||||
viewports,
|
||||
|
@ -107,6 +119,7 @@ let App = createClass({
|
|||
|
||||
let {
|
||||
onBrowserMounted,
|
||||
onChangeNetworkThrottling,
|
||||
onChangeViewportDevice,
|
||||
onContentResize,
|
||||
onDeviceListUpdate,
|
||||
|
@ -124,8 +137,10 @@ let App = createClass({
|
|||
id: "app",
|
||||
},
|
||||
GlobalToolbar({
|
||||
networkThrottling,
|
||||
screenshot,
|
||||
touchSimulation,
|
||||
onChangeNetworkThrottling,
|
||||
onExit,
|
||||
onScreenshot,
|
||||
onUpdateTouchSimulation,
|
||||
|
|
|
@ -4,17 +4,21 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { getStr } = require("../utils/l10n");
|
||||
const { DOM: dom, createClass, PropTypes, addons } =
|
||||
const { DOM: dom, createClass, createFactory, PropTypes, addons } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
|
||||
const { getStr } = require("../utils/l10n");
|
||||
const Types = require("../types");
|
||||
const NetworkThrottlingSelector = createFactory(require("./network-throttling-selector"));
|
||||
|
||||
module.exports = createClass({
|
||||
displayName: "GlobalToolbar",
|
||||
|
||||
propTypes: {
|
||||
networkThrottling: PropTypes.shape(Types.networkThrottling).isRequired,
|
||||
screenshot: PropTypes.shape(Types.screenshot).isRequired,
|
||||
touchSimulation: PropTypes.shape(Types.touchSimulation).isRequired,
|
||||
onChangeNetworkThrottling: PropTypes.func.isRequired,
|
||||
onExit: PropTypes.func.isRequired,
|
||||
onScreenshot: PropTypes.func.isRequired,
|
||||
onUpdateTouchSimulation: PropTypes.func.isRequired,
|
||||
|
@ -24,8 +28,10 @@ module.exports = createClass({
|
|||
|
||||
render() {
|
||||
let {
|
||||
networkThrottling,
|
||||
screenshot,
|
||||
touchSimulation,
|
||||
onChangeNetworkThrottling,
|
||||
onExit,
|
||||
onScreenshot,
|
||||
onUpdateTouchSimulation
|
||||
|
@ -45,7 +51,12 @@ module.exports = createClass({
|
|||
{
|
||||
className: "title",
|
||||
},
|
||||
getStr("responsive.title")),
|
||||
getStr("responsive.title")
|
||||
),
|
||||
NetworkThrottlingSelector({
|
||||
networkThrottling,
|
||||
onChangeNetworkThrottling,
|
||||
}),
|
||||
dom.button({
|
||||
id: "global-touch-simulation-button",
|
||||
className: touchButtonClass,
|
||||
|
|
|
@ -9,6 +9,7 @@ DevToolsModules(
|
|||
'device-modal.js',
|
||||
'device-selector.js',
|
||||
'global-toolbar.js',
|
||||
'network-throttling-selector.js',
|
||||
'resizable-viewport.js',
|
||||
'viewport-dimension.js',
|
||||
'viewport-toolbar.js',
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { DOM: dom, createClass, PropTypes, addons } =
|
||||
require("devtools/client/shared/vendor/react");
|
||||
|
||||
const Types = require("../types");
|
||||
const { getStr } = require("../utils/l10n");
|
||||
const throttlingProfiles = require("devtools/client/shared/network-throttling-profiles");
|
||||
|
||||
module.exports = createClass({
|
||||
|
||||
displayName: "NetworkThrottlingSelector",
|
||||
|
||||
propTypes: {
|
||||
networkThrottling: PropTypes.shape(Types.networkThrottling).isRequired,
|
||||
onChangeNetworkThrottling: PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
mixins: [ addons.PureRenderMixin ],
|
||||
|
||||
onSelectChange({ target }) {
|
||||
let {
|
||||
onChangeNetworkThrottling,
|
||||
} = this.props;
|
||||
|
||||
if (target.value == getStr("responsive.noThrottling")) {
|
||||
onChangeNetworkThrottling(false, "");
|
||||
return;
|
||||
}
|
||||
|
||||
for (let profile of throttlingProfiles) {
|
||||
if (profile.id === target.value) {
|
||||
onChangeNetworkThrottling(true, profile.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
render() {
|
||||
let {
|
||||
networkThrottling,
|
||||
} = this.props;
|
||||
|
||||
let selectClass = "";
|
||||
let selectedProfile;
|
||||
if (networkThrottling.enabled) {
|
||||
selectClass += " selected";
|
||||
selectedProfile = networkThrottling.profile;
|
||||
} else {
|
||||
selectedProfile = getStr("responsive.noThrottling");
|
||||
}
|
||||
|
||||
let listContent = [
|
||||
dom.option(
|
||||
{
|
||||
key: "disabled",
|
||||
},
|
||||
getStr("responsive.noThrottling")
|
||||
),
|
||||
dom.option(
|
||||
{
|
||||
key: "divider",
|
||||
className: "divider",
|
||||
disabled: true,
|
||||
}
|
||||
),
|
||||
throttlingProfiles.map(profile => {
|
||||
return dom.option(
|
||||
{
|
||||
key: profile.id,
|
||||
},
|
||||
profile.id
|
||||
);
|
||||
}),
|
||||
];
|
||||
|
||||
return dom.select(
|
||||
{
|
||||
id: "global-network-throttling-selector",
|
||||
className: selectClass,
|
||||
value: selectedProfile,
|
||||
onChange: this.onSelectChange,
|
||||
},
|
||||
...listContent
|
||||
);
|
||||
},
|
||||
|
||||
});
|
|
@ -55,7 +55,7 @@ html, body {
|
|||
}
|
||||
|
||||
/**
|
||||
* Common style for containers and toolbar buttons
|
||||
* Common styles for shared components
|
||||
*/
|
||||
|
||||
.container {
|
||||
|
@ -77,6 +77,57 @@ html, body {
|
|||
filter: url("chrome://devtools/skin/images/filters.svg#checked-icon-state");
|
||||
}
|
||||
|
||||
select {
|
||||
-moz-appearance: none;
|
||||
background-color: var(--theme-toolbar-background);
|
||||
background-image: var(--viewport-selection-arrow);
|
||||
background-position: 100% 50%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 7px;
|
||||
border: none;
|
||||
color: var(--viewport-color);
|
||||
padding: 0 8px;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
select.selected {
|
||||
background-image: var(--viewport-selection-arrow-selected);
|
||||
color: var(--viewport-active-color);
|
||||
}
|
||||
|
||||
select:hover {
|
||||
background-image: var(--viewport-selection-arrow-hovered);
|
||||
color: var(--viewport-hover-color);
|
||||
}
|
||||
|
||||
/* This is (believed to be?) separate from the identical select.selected rule
|
||||
set so that it overrides select:hover because of file ordering once the
|
||||
select is focused. It's unclear whether the visual effect that results here
|
||||
is intentional and desired. */
|
||||
select:focus {
|
||||
background-image: var(--viewport-selection-arrow-selected);
|
||||
color: var(--viewport-active-color);
|
||||
}
|
||||
|
||||
select > option {
|
||||
text-align: left;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
select > option,
|
||||
select > option:hover {
|
||||
color: var(--viewport-active-color);
|
||||
}
|
||||
|
||||
select > option.divider {
|
||||
border-top: 1px solid var(--theme-splitter-color);
|
||||
height: 0px;
|
||||
padding: 0;
|
||||
font-size: 0px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Toolbar
|
||||
*/
|
||||
|
@ -131,6 +182,11 @@ html, body {
|
|||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
#global-network-throttling-selector {
|
||||
height: 15px;
|
||||
padding-left: 0;
|
||||
width: 103px;
|
||||
}
|
||||
|
||||
#viewports {
|
||||
/* Make sure left-most viewport is visible when there's horizontal overflow.
|
||||
|
@ -172,50 +228,6 @@ html, body {
|
|||
height: 18px;
|
||||
}
|
||||
|
||||
.viewport-device-selector {
|
||||
-moz-appearance: none;
|
||||
background-color: var(--theme-toolbar-background);
|
||||
background-image: var(--viewport-selection-arrow);
|
||||
background-position: 100% 52%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 7px;
|
||||
border: none;
|
||||
color: var(--viewport-color);
|
||||
height: 100%;
|
||||
padding: 0 8px 0 8px;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
width: 150px;
|
||||
font-size: 11px;
|
||||
width: -moz-fit-content;
|
||||
}
|
||||
|
||||
.viewport-device-selector.selected {
|
||||
background-image: var(--viewport-selection-arrow-selected);
|
||||
color: var(--viewport-active-color);
|
||||
}
|
||||
|
||||
.viewport-device-selector:hover {
|
||||
background-image: var(--viewport-selection-arrow-hovered);
|
||||
color: var(--viewport-hover-color);
|
||||
}
|
||||
|
||||
.viewport-device-selector:focus {
|
||||
background-image: var(--viewport-selection-arrow-selected);
|
||||
color: var(--viewport-active-color);
|
||||
}
|
||||
|
||||
.viewport-device-selector > option {
|
||||
text-align: left;
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.viewport-device-selector > option,
|
||||
.viewport-device-selector > option:hover,
|
||||
.viewport-device-selector:hover > option:hover {
|
||||
color: var(--viewport-active-color);
|
||||
}
|
||||
|
||||
.viewport-rotate-button {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
|
|
|
@ -14,15 +14,15 @@ const message = require("./utils/message");
|
|||
const { swapToInnerBrowser } = require("./browser/swap");
|
||||
const { EmulationFront } = require("devtools/shared/fronts/emulation");
|
||||
const { getStr } = require("./utils/l10n");
|
||||
const { TargetFactory } = require("devtools/client/framework/target");
|
||||
const { gDevTools } = require("devtools/client/framework/devtools");
|
||||
|
||||
const TOOL_URL = "chrome://devtools/content/responsive.html/index.xhtml";
|
||||
|
||||
loader.lazyRequireGetter(this, "DebuggerClient",
|
||||
"devtools/shared/client/main", true);
|
||||
loader.lazyRequireGetter(this, "DebuggerServer",
|
||||
"devtools/server/main", true);
|
||||
loader.lazyRequireGetter(this, "DebuggerClient", "devtools/shared/client/main", true);
|
||||
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
|
||||
loader.lazyRequireGetter(this, "TargetFactory", "devtools/client/framework/target", true);
|
||||
loader.lazyRequireGetter(this, "gDevTools", "devtools/client/framework/devtools", true);
|
||||
loader.lazyRequireGetter(this, "throttlingProfiles",
|
||||
"devtools/client/shared/network-throttling-profiles");
|
||||
|
||||
/**
|
||||
* ResponsiveUIManager is the external API for the browser UI, etc. to use when
|
||||
|
@ -362,9 +362,6 @@ ResponsiveUI.prototype = {
|
|||
this.toolWindow.removeEventListener("message", this);
|
||||
|
||||
if (!isTabClosing) {
|
||||
// Stop the touch event simulator if it was running
|
||||
yield this.emulationFront.clearTouchEventsOverride();
|
||||
|
||||
// Notify the inner browser to stop the frame script
|
||||
yield message.request(this.toolWindow, "stop-frame-script");
|
||||
}
|
||||
|
@ -377,7 +374,9 @@ ResponsiveUI.prototype = {
|
|||
this.toolWindow = null;
|
||||
this.swap = null;
|
||||
|
||||
// Close the debugger client used to speak with emulation actor
|
||||
// Close the debugger client used to speak with emulation actor.
|
||||
// The actor handles clearing any overrides itself, so it's not necessary to clear
|
||||
// anything on shutdown client side.
|
||||
let clientClosed = this.client.close();
|
||||
if (!isTabClosing) {
|
||||
yield clientClosed;
|
||||
|
@ -422,65 +421,104 @@ ResponsiveUI.prototype = {
|
|||
},
|
||||
|
||||
handleMessage(event) {
|
||||
let { browserWindow, tab } = this;
|
||||
|
||||
if (event.origin !== "chrome://devtools") {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.data.type) {
|
||||
case "change-network-throtting":
|
||||
this.onChangeNetworkThrottling(event);
|
||||
break;
|
||||
case "change-viewport-device":
|
||||
let { userAgent, pixelRatio, touch } = event.data.device;
|
||||
this.updateUserAgent(userAgent);
|
||||
this.updateDPPX(pixelRatio);
|
||||
this.updateTouchSimulation(touch);
|
||||
this.onChangeViewportDevice(event);
|
||||
break;
|
||||
case "content-resize":
|
||||
let { width, height } = event.data;
|
||||
this.emit("content-resize", {
|
||||
width,
|
||||
height,
|
||||
});
|
||||
this.onContentResize(event);
|
||||
break;
|
||||
case "exit":
|
||||
ResponsiveUIManager.closeIfNeeded(browserWindow, tab);
|
||||
this.onExit();
|
||||
break;
|
||||
case "update-touch-simulation":
|
||||
let { enabled } = event.data;
|
||||
this.updateTouchSimulation(enabled);
|
||||
this.onUpdateTouchSimulation(event);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
updateTouchSimulation: Task.async(function* (enabled) {
|
||||
if (enabled) {
|
||||
let reloadNeeded = yield this.emulationFront.setTouchEventsOverride(
|
||||
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED
|
||||
);
|
||||
if (reloadNeeded) {
|
||||
this.getViewportBrowser().reload();
|
||||
}
|
||||
} else {
|
||||
this.emulationFront.clearTouchEventsOverride();
|
||||
}
|
||||
onChangeNetworkThrottling: Task.async(function* (event) {
|
||||
let { enabled, profile } = event.data;
|
||||
yield this.updateNetworkThrottling(enabled, profile);
|
||||
// Used by tests
|
||||
this.emit("network-throttling-changed");
|
||||
}),
|
||||
|
||||
updateUserAgent(userAgent) {
|
||||
if (userAgent) {
|
||||
this.emulationFront.setUserAgentOverride(userAgent);
|
||||
} else {
|
||||
this.emulationFront.clearUserAgentOverride();
|
||||
}
|
||||
onChangeViewportDevice(event) {
|
||||
let { userAgent, pixelRatio, touch } = event.data.device;
|
||||
this.updateUserAgent(userAgent);
|
||||
this.updateDPPX(pixelRatio);
|
||||
this.updateTouchSimulation(touch);
|
||||
},
|
||||
|
||||
onContentResize(event) {
|
||||
let { width, height } = event.data;
|
||||
this.emit("content-resize", {
|
||||
width,
|
||||
height,
|
||||
});
|
||||
},
|
||||
|
||||
onExit() {
|
||||
let { browserWindow, tab } = this;
|
||||
ResponsiveUIManager.closeIfNeeded(browserWindow, tab);
|
||||
},
|
||||
|
||||
onUpdateTouchSimulation(event) {
|
||||
let { enabled } = event.data;
|
||||
this.updateTouchSimulation(enabled);
|
||||
},
|
||||
|
||||
updateDPPX(dppx) {
|
||||
if (dppx) {
|
||||
this.emulationFront.setDPPXOverride(dppx);
|
||||
} else {
|
||||
if (!dppx) {
|
||||
this.emulationFront.clearDPPXOverride();
|
||||
return;
|
||||
}
|
||||
this.emulationFront.setDPPXOverride(dppx);
|
||||
},
|
||||
|
||||
updateNetworkThrottling: Task.async(function* (enabled, profile) {
|
||||
if (!enabled) {
|
||||
yield this.emulationFront.clearNetworkThrottling();
|
||||
return;
|
||||
}
|
||||
let data = throttlingProfiles.find(({ id }) => id == profile);
|
||||
let { download, upload, latency } = data;
|
||||
yield this.emulationFront.setNetworkThrottling({
|
||||
downloadThroughput: download,
|
||||
uploadThroughput: upload,
|
||||
latency,
|
||||
});
|
||||
}),
|
||||
|
||||
updateUserAgent(userAgent) {
|
||||
if (!userAgent) {
|
||||
this.emulationFront.clearUserAgentOverride();
|
||||
return;
|
||||
}
|
||||
this.emulationFront.setUserAgentOverride(userAgent);
|
||||
},
|
||||
|
||||
updateTouchSimulation: Task.async(function* (enabled) {
|
||||
if (!enabled) {
|
||||
yield this.emulationFront.clearTouchEventsOverride();
|
||||
return;
|
||||
}
|
||||
let reloadNeeded = yield this.emulationFront.setTouchEventsOverride(
|
||||
Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED
|
||||
);
|
||||
if (reloadNeeded) {
|
||||
this.getViewportBrowser().reload();
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Helper for tests. Assumes a single viewport for now.
|
||||
*/
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
exports.devices = require("./reducers/devices");
|
||||
exports.location = require("./reducers/location");
|
||||
exports.networkThrottling = require("./reducers/network-throttling");
|
||||
exports.screenshot = require("./reducers/screenshot");
|
||||
exports.touchSimulation = require("./reducers/touch-simulation");
|
||||
exports.viewports = require("./reducers/viewports");
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
DevToolsModules(
|
||||
'devices.js',
|
||||
'location.js',
|
||||
'network-throttling.js',
|
||||
'screenshot.js',
|
||||
'touch-simulation.js',
|
||||
'viewports.js',
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
CHANGE_NETWORK_THROTTLING,
|
||||
} = require("../actions/index");
|
||||
|
||||
const INITIAL_NETWORK_THROTTLING = {
|
||||
enabled: false,
|
||||
profile: "",
|
||||
};
|
||||
|
||||
let reducers = {
|
||||
|
||||
[CHANGE_NETWORK_THROTTLING](throttling, { enabled, profile }) {
|
||||
return {
|
||||
enabled,
|
||||
profile,
|
||||
};
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
module.exports = function (throttling = INITIAL_NETWORK_THROTTLING, action) {
|
||||
let reducer = reducers[action.type];
|
||||
if (!reducer) {
|
||||
return throttling;
|
||||
}
|
||||
return reducer(throttling, action);
|
||||
};
|
|
@ -27,6 +27,7 @@ support-files =
|
|||
[browser_menu_item_02.js]
|
||||
[browser_mouse_resize.js]
|
||||
[browser_navigation.js]
|
||||
[browser_network_throttling.js]
|
||||
[browser_page_state.js]
|
||||
[browser_permission_doorhanger.js]
|
||||
[browser_resize_cmd.js]
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const throttlingProfiles = require("devtools/client/shared/network-throttling-profiles");
|
||||
|
||||
// Tests changing network throttling
|
||||
const TEST_URL = "data:text/html;charset=utf-8,Network throttling test";
|
||||
|
||||
addRDMTask(TEST_URL, function* ({ ui, manager }) {
|
||||
let { store } = ui.toolWindow;
|
||||
|
||||
// Wait until the viewport has been added
|
||||
yield waitUntilState(store, state => state.viewports.length == 1);
|
||||
|
||||
// Test defaults
|
||||
testNetworkThrottlingSelectorLabel(ui, "No throttling");
|
||||
yield testNetworkThrottlingState(ui, null);
|
||||
|
||||
// Test a fast profile
|
||||
yield testThrottlingProfile(ui, "Wi-Fi");
|
||||
|
||||
// Test a slower profile
|
||||
yield testThrottlingProfile(ui, "Regular 3G");
|
||||
|
||||
// Test switching back to no throttling
|
||||
let changed = once(ui, "network-throttling-changed");
|
||||
yield switchNetworkThrottling(ui, "No throttling");
|
||||
yield changed;
|
||||
testNetworkThrottlingSelectorLabel(ui, "No throttling");
|
||||
yield testNetworkThrottlingState(ui, null);
|
||||
});
|
||||
|
||||
function testNetworkThrottlingSelectorLabel(ui, expected) {
|
||||
let selector = "#global-network-throttling-selector";
|
||||
let select = ui.toolWindow.document.querySelector(selector);
|
||||
is(select.selectedOptions[0].textContent, expected,
|
||||
`Select label should be changed to ${expected}`);
|
||||
}
|
||||
|
||||
var testNetworkThrottlingState = Task.async(function* (ui, expected) {
|
||||
let state = yield ui.emulationFront.getNetworkThrottling();
|
||||
Assert.deepEqual(state, expected, "Network throttling state should be " +
|
||||
JSON.stringify(expected, null, 2));
|
||||
});
|
||||
|
||||
var testThrottlingProfile = Task.async(function* (ui, profile) {
|
||||
let changed = once(ui, "network-throttling-changed");
|
||||
yield switchNetworkThrottling(ui, profile);
|
||||
yield changed;
|
||||
testNetworkThrottlingSelectorLabel(ui, profile);
|
||||
let data = throttlingProfiles.find(({ id }) => id == profile);
|
||||
let { download, upload, latency } = data;
|
||||
yield testNetworkThrottlingState(ui, {
|
||||
downloadThroughput: download,
|
||||
uploadThroughput: upload,
|
||||
latency,
|
||||
});
|
||||
});
|
|
@ -230,9 +230,8 @@ function openDeviceModal(ui) {
|
|||
"The device modal is displayed.");
|
||||
}
|
||||
|
||||
function switchDevice({ toolWindow }, value) {
|
||||
function switchSelector({ toolWindow }, selector, value) {
|
||||
return new Promise(resolve => {
|
||||
let selector = ".viewport-device-selector";
|
||||
let select = toolWindow.document.querySelector(selector);
|
||||
isnot(select, null, `selector "${selector}" should match an existing element.`);
|
||||
|
||||
|
@ -256,6 +255,14 @@ function switchDevice({ toolWindow }, value) {
|
|||
});
|
||||
}
|
||||
|
||||
function switchDevice(ui, value) {
|
||||
return switchSelector(ui, ".viewport-device-selector", value);
|
||||
}
|
||||
|
||||
function switchNetworkThrottling(ui, value) {
|
||||
return switchSelector(ui, "#global-network-throttling-selector", value);
|
||||
}
|
||||
|
||||
function getSessionHistory(browser) {
|
||||
return ContentTask.spawn(browser, {}, function* () {
|
||||
/* eslint-disable no-undef */
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test changing the network throttling state
|
||||
|
||||
const {
|
||||
changeNetworkThrottling,
|
||||
} = require("devtools/client/responsive.html/actions/network-throttling");
|
||||
|
||||
add_task(function* () {
|
||||
let store = Store();
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
ok(!getState().networkThrottling.enabled,
|
||||
"Network throttling is disabled by default.");
|
||||
equal(getState().networkThrottling.profile, "",
|
||||
"Network throttling profile is empty by default.");
|
||||
|
||||
dispatch(changeNetworkThrottling(true, "Bob"));
|
||||
|
||||
ok(getState().networkThrottling.enabled,
|
||||
"Network throttling is enabled.");
|
||||
equal(getState().networkThrottling.profile, "Bob",
|
||||
"Network throttling profile is set.");
|
||||
});
|
|
@ -8,6 +8,7 @@ firefox-appdir = browser
|
|||
[test_add_device_type.js]
|
||||
[test_add_viewport.js]
|
||||
[test_change_location.js]
|
||||
[test_change_network_throttling.js]
|
||||
[test_change_viewport_device.js]
|
||||
[test_resize_viewport.js]
|
||||
[test_rotate_viewport.js]
|
||||
|
|
|
@ -95,7 +95,7 @@ exports.location = PropTypes.string;
|
|||
*/
|
||||
exports.screenshot = {
|
||||
|
||||
isCapturing: PropTypes.bool.isRequired,
|
||||
isCapturing: PropTypes.bool,
|
||||
|
||||
};
|
||||
|
||||
|
@ -104,8 +104,21 @@ exports.screenshot = {
|
|||
*/
|
||||
exports.touchSimulation = {
|
||||
|
||||
// Whether or not the touch simulation is enabled
|
||||
enabled: PropTypes.bool.isRequired,
|
||||
// Whether or not touch simulation is enabled
|
||||
enabled: PropTypes.bool,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Network throttling.
|
||||
*/
|
||||
exports.networkThrottling = {
|
||||
|
||||
// Whether or not network throttling is enabled
|
||||
enabled: PropTypes.bool,
|
||||
|
||||
// Name of the selected throttling profile
|
||||
profile: PropTypes.string,
|
||||
|
||||
};
|
||||
|
||||
|
@ -115,7 +128,7 @@ exports.touchSimulation = {
|
|||
exports.viewport = {
|
||||
|
||||
// The id of the viewport
|
||||
id: PropTypes.number.isRequired,
|
||||
id: PropTypes.number,
|
||||
|
||||
// The currently selected device applied to the viewport.
|
||||
device: PropTypes.string,
|
||||
|
|
|
@ -36,6 +36,7 @@ DevToolsModules(
|
|||
'Jsbeautify.jsm',
|
||||
'key-shortcuts.js',
|
||||
'keycodes.js',
|
||||
'network-throttling-profiles.js',
|
||||
'node-attribute-parser.js',
|
||||
'options-view.js',
|
||||
'output-parser.js',
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const K = 1024;
|
||||
const M = 1024 * 1024;
|
||||
const Bps = 1 / 8;
|
||||
const KBps = K * Bps;
|
||||
const MBps = M * Bps;
|
||||
|
||||
/**
|
||||
* Predefined network throttling profiles.
|
||||
* Speeds are in bytes per second. Latency is in ms.
|
||||
*/
|
||||
/* eslint-disable key-spacing */
|
||||
module.exports = [
|
||||
{
|
||||
id: "GPRS",
|
||||
download: 50 * KBps,
|
||||
upload: 20 * KBps,
|
||||
latency: 500,
|
||||
},
|
||||
{
|
||||
id: "Regular 2G",
|
||||
download: 250 * KBps,
|
||||
upload: 50 * KBps,
|
||||
latency: 300,
|
||||
},
|
||||
{
|
||||
id: "Good 2G",
|
||||
download: 450 * KBps,
|
||||
upload: 150 * KBps,
|
||||
latency: 150,
|
||||
},
|
||||
{
|
||||
id: "Regular 3G",
|
||||
download: 750 * KBps,
|
||||
upload: 250 * KBps,
|
||||
latency: 100,
|
||||
},
|
||||
{
|
||||
id: "Good 3G",
|
||||
download: 1.5 * MBps,
|
||||
upload: 750 * KBps,
|
||||
latency: 40,
|
||||
},
|
||||
{
|
||||
id: "Regular 4G / LTE",
|
||||
download: 4 * MBps,
|
||||
upload: 3 * MBps,
|
||||
latency: 20,
|
||||
},
|
||||
{
|
||||
id: "DSL",
|
||||
download: 2 * MBps,
|
||||
upload: 1 * MBps,
|
||||
latency: 5,
|
||||
},
|
||||
{
|
||||
id: "Wi-Fi",
|
||||
download: 30 * MBps,
|
||||
upload: 15 * MBps,
|
||||
latency: 2,
|
||||
},
|
||||
];
|
||||
/* eslint-enable key-spacing */
|
Загрузка…
Ссылка в новой задаче