зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central and fx-team
This commit is contained in:
Коммит
af0a1da034
|
@ -1166,6 +1166,9 @@ pref("devtools.scratchpad.recentFilesMax", 10);
|
|||
pref("devtools.styleeditor.enabled", true);
|
||||
pref("devtools.styleeditor.transitions", true);
|
||||
|
||||
// Enable the Shader Editor.
|
||||
pref("devtools.shadereditor.enabled", false);
|
||||
|
||||
// Enable tools for Chrome development.
|
||||
pref("devtools.chrome.enabled", false);
|
||||
|
||||
|
|
|
@ -10,9 +10,7 @@ let Ci = Components.interfaces;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PageThumbs.jsm");
|
||||
#ifndef RELEASE_BUILD
|
||||
Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm");
|
||||
#endif
|
||||
Cu.import("resource://gre/modules/NewTabUtils.jsm");
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
|
|
|
@ -131,12 +131,10 @@ Site.prototype = {
|
|||
|
||||
if (this.isPinned())
|
||||
this._updateAttributes(true);
|
||||
#ifndef RELEASE_BUILD
|
||||
// request a staleness check for the thumbnail, which will cause page.js
|
||||
// Capture the page if the thumbnail is missing, which will cause page.js
|
||||
// to be notified and call our refreshThumbnail() method.
|
||||
BackgroundPageThumbs.captureIfMissing(this.url);
|
||||
// but still display whatever thumbnail might be available now.
|
||||
#endif
|
||||
this.refreshThumbnail();
|
||||
},
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
const nsIPermissionManager = Components.interfaces.nsIPermissionManager;
|
||||
const nsICookiePermission = Components.interfaces.nsICookiePermission;
|
||||
|
||||
const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions";
|
||||
|
||||
function Permission(host, rawHost, type, capability, perm)
|
||||
{
|
||||
this.host = host;
|
||||
|
@ -183,6 +185,7 @@ var gPermissionManager = {
|
|||
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.notifyObservers(null, NOTIFICATION_FLUSH_PERMISSIONS, this._type);
|
||||
os.addObserver(this, "perm-changed", false);
|
||||
|
||||
this._loadPermissions();
|
||||
|
|
|
@ -42,9 +42,13 @@ ManifestEditor.prototype = {
|
|||
_onContainerReady: function(varWindow) {
|
||||
let variablesContainer = varWindow.document.querySelector("#variables");
|
||||
|
||||
variablesContainer.classList.add("manifest-editor");
|
||||
|
||||
let editor = this.editor = new VariablesView(variablesContainer);
|
||||
|
||||
editor.onlyEnumVisible = true;
|
||||
editor.alignedValues = true;
|
||||
editor.actionsFirst = true;
|
||||
|
||||
if (this.editable) {
|
||||
editor.eval = this._onEval;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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
|
||||
|
|
|
@ -51,6 +51,8 @@ browser.jar:
|
|||
content/browser/devtools/debugger-view.js (debugger/debugger-view.js)
|
||||
content/browser/devtools/debugger-toolbar.js (debugger/debugger-toolbar.js)
|
||||
content/browser/devtools/debugger-panes.js (debugger/debugger-panes.js)
|
||||
content/browser/devtools/shadereditor.xul (shadereditor/shadereditor.xul)
|
||||
content/browser/devtools/shadereditor.js (shadereditor/shadereditor.js)
|
||||
content/browser/devtools/profiler.xul (profiler/profiler.xul)
|
||||
content/browser/devtools/cleopatra.html (profiler/cleopatra/cleopatra.html)
|
||||
content/browser/devtools/profiler/cleopatra/css/ui.css (profiler/cleopatra/css/ui.css)
|
||||
|
|
|
@ -27,6 +27,7 @@ loader.lazyGetter(this, "InspectorPanel", () => require("devtools/inspector/insp
|
|||
loader.lazyGetter(this, "WebConsolePanel", () => require("devtools/webconsole/panel").WebConsolePanel);
|
||||
loader.lazyGetter(this, "DebuggerPanel", () => require("devtools/debugger/debugger-panel").DebuggerPanel);
|
||||
loader.lazyImporter(this, "StyleEditorPanel", "resource:///modules/devtools/StyleEditorPanel.jsm");
|
||||
loader.lazyGetter(this, "ShaderEditorPanel", () => require("devtools/shadereditor/panel").ShaderEditorPanel);
|
||||
loader.lazyGetter(this, "ProfilerPanel", () => require("devtools/profiler/panel"));
|
||||
loader.lazyGetter(this, "NetMonitorPanel", () => require("devtools/netmonitor/netmonitor-panel").NetMonitorPanel);
|
||||
loader.lazyGetter(this, "ScratchpadPanel", () => require("devtools/scratchpad/scratchpad-panel").ScratchpadPanel);
|
||||
|
@ -36,6 +37,7 @@ const toolboxProps = "chrome://browser/locale/devtools/toolbox.properties";
|
|||
const inspectorProps = "chrome://browser/locale/devtools/inspector.properties";
|
||||
const debuggerProps = "chrome://browser/locale/devtools/debugger.properties";
|
||||
const styleEditorProps = "chrome://browser/locale/devtools/styleeditor.properties";
|
||||
const shaderEditorProps = "chrome://browser/locale/devtools/shadereditor.properties";
|
||||
const webConsoleProps = "chrome://browser/locale/devtools/webconsole.properties";
|
||||
const profilerProps = "chrome://browser/locale/devtools/profiler.properties";
|
||||
const netMonitorProps = "chrome://browser/locale/devtools/netmonitor.properties";
|
||||
|
@ -44,6 +46,7 @@ loader.lazyGetter(this, "toolboxStrings", () => Services.strings.createBundle(to
|
|||
loader.lazyGetter(this, "webConsoleStrings", () => Services.strings.createBundle(webConsoleProps));
|
||||
loader.lazyGetter(this, "debuggerStrings", () => Services.strings.createBundle(debuggerProps));
|
||||
loader.lazyGetter(this, "styleEditorStrings", () => Services.strings.createBundle(styleEditorProps));
|
||||
loader.lazyGetter(this, "shaderEditorStrings", () => Services.strings.createBundle(shaderEditorProps));
|
||||
loader.lazyGetter(this, "inspectorStrings", () => Services.strings.createBundle(inspectorProps));
|
||||
loader.lazyGetter(this, "profilerStrings",() => Services.strings.createBundle(profilerProps));
|
||||
loader.lazyGetter(this, "netMonitorStrings", () => Services.strings.createBundle(netMonitorProps));
|
||||
|
@ -166,11 +169,30 @@ Tools.styleEditor = {
|
|||
}
|
||||
};
|
||||
|
||||
Tools.shaderEditor = {
|
||||
id: "shadereditor",
|
||||
ordinal: 5,
|
||||
visibilityswitch: "devtools.shadereditor.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-styleeditor.png",
|
||||
url: "chrome://browser/content/devtools/shadereditor.xul",
|
||||
label: l10n("ToolboxShaderEditor.label", shaderEditorStrings),
|
||||
tooltip: l10n("ToolboxShaderEditor.tooltip", shaderEditorStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return true;
|
||||
},
|
||||
|
||||
build: function(iframeWindow, toolbox) {
|
||||
let panel = new ShaderEditorPanel(iframeWindow, toolbox);
|
||||
return panel.open();
|
||||
}
|
||||
};
|
||||
|
||||
Tools.jsprofiler = {
|
||||
id: "jsprofiler",
|
||||
accesskey: l10n("profiler.accesskey", profilerStrings),
|
||||
key: l10n("profiler2.commandkey", profilerStrings),
|
||||
ordinal: 5,
|
||||
ordinal: 6,
|
||||
modifiers: "shift",
|
||||
visibilityswitch: "devtools.profiler.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-profiler.png",
|
||||
|
@ -193,7 +215,7 @@ Tools.netMonitor = {
|
|||
id: "netmonitor",
|
||||
accesskey: l10n("netmonitor.accesskey", netMonitorStrings),
|
||||
key: l10n("netmonitor.commandkey", netMonitorStrings),
|
||||
ordinal: 6,
|
||||
ordinal: 7,
|
||||
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
|
||||
visibilityswitch: "devtools.netmonitor.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-network.png",
|
||||
|
@ -214,7 +236,7 @@ Tools.netMonitor = {
|
|||
|
||||
Tools.scratchpad = {
|
||||
id: "scratchpad",
|
||||
ordinal: 7,
|
||||
ordinal: 8,
|
||||
visibilityswitch: "devtools.scratchpad.enabled",
|
||||
icon: "chrome://browser/skin/devtools/tool-scratchpad.png",
|
||||
url: "chrome://browser/content/devtools/scratchpad.xul",
|
||||
|
@ -234,10 +256,11 @@ Tools.scratchpad = {
|
|||
|
||||
let defaultTools = [
|
||||
Tools.options,
|
||||
Tools.styleEditor,
|
||||
Tools.webConsole,
|
||||
Tools.jsdebugger,
|
||||
Tools.inspector,
|
||||
Tools.jsdebugger,
|
||||
Tools.styleEditor,
|
||||
Tools.shaderEditor,
|
||||
Tools.jsprofiler,
|
||||
Tools.netMonitor,
|
||||
Tools.scratchpad
|
||||
|
|
|
@ -5,24 +5,25 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'inspector',
|
||||
'markupview',
|
||||
'webconsole',
|
||||
'app-manager',
|
||||
'commandline',
|
||||
'debugger',
|
||||
'fontinspector',
|
||||
'framework',
|
||||
'inspector',
|
||||
'layoutview',
|
||||
'markupview',
|
||||
'netmonitor',
|
||||
'profiler',
|
||||
'responsivedesign',
|
||||
'scratchpad',
|
||||
'shadereditor',
|
||||
'shared',
|
||||
'sourceeditor',
|
||||
'styleeditor',
|
||||
'styleinspector',
|
||||
'tilt',
|
||||
'scratchpad',
|
||||
'debugger',
|
||||
'netmonitor',
|
||||
'layoutview',
|
||||
'shared',
|
||||
'responsivedesign',
|
||||
'framework',
|
||||
'profiler',
|
||||
'fontinspector',
|
||||
'app-manager',
|
||||
'webconsole',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
|
|
|
@ -2044,6 +2044,7 @@ NetworkDetailsView.prototype = {
|
|||
* DOM query helper.
|
||||
*/
|
||||
function $(aSelector, aTarget = document) aTarget.querySelector(aSelector);
|
||||
function $all(aSelector, aTarget = document) aTarget.querySelectorAll(aSelector);
|
||||
|
||||
/**
|
||||
* Helper for getting an nsIURL instance out of a string.
|
||||
|
|
|
@ -9,7 +9,7 @@ function test() {
|
|||
initNetMonitor(STATUS_CODES_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { $all, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
@ -182,6 +182,8 @@ function test() {
|
|||
"There should be a total of 5 items in the requests menu.");
|
||||
is(RequestsMenu.visibleItems.length, 5,
|
||||
"There should be a total of 5 visbile items in the requests menu.");
|
||||
is($all(".side-menu-widget-item").length, 5,
|
||||
"The visible items in the requests menu are, in fact, visible!");
|
||||
|
||||
is(RequestsMenu.getItemAtIndex(0), RequestsMenu.items[0],
|
||||
"The requests menu items aren't ordered correctly. First item is misplaced.");
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
// of the heavy dom manipulation associated with sorting.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
let { $, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { $, $all, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
@ -178,6 +178,8 @@ function test() {
|
|||
"There should be a total of 5 items in the requests menu.");
|
||||
is(RequestsMenu.visibleItems.length, 5,
|
||||
"There should be a total of 5 visbile items in the requests menu.");
|
||||
is($all(".side-menu-widget-item").length, 5,
|
||||
"The visible items in the requests menu are, in fact, visible!");
|
||||
|
||||
is(RequestsMenu.getItemAtIndex(0), RequestsMenu.items[0],
|
||||
"The requests menu items aren't ordered correctly. First item is misplaced.");
|
||||
|
|
|
@ -13,7 +13,7 @@ function test() {
|
|||
// of the heavy dom manipulation associated with sorting.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
let { $, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { $, $all, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
RequestsMenu.lazyUpdate = false;
|
||||
|
@ -114,6 +114,8 @@ function test() {
|
|||
"There should be a specific number of items in the requests menu.");
|
||||
is(RequestsMenu.visibleItems.length, aOrder.length,
|
||||
"There should be a specific number of visbile items in the requests menu.");
|
||||
is($all(".side-menu-widget-item").length, aOrder.length,
|
||||
"The visible items in the requests menu are, in fact, visible!");
|
||||
|
||||
for (let i = 0; i < aOrder.length; i++) {
|
||||
is(RequestsMenu.getItemAtIndex(i), RequestsMenu.items[i],
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
JS_MODULES_PATH = 'modules/devtools/shadereditor'
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'panel.js'
|
||||
]
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* 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 { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const promise = require("sdk/core/promise");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { WebGLFront } = require("devtools/server/actors/webgl");
|
||||
|
||||
function ShaderEditorPanel(iframeWindow, toolbox) {
|
||||
this.panelWin = iframeWindow;
|
||||
this._toolbox = toolbox;
|
||||
this._destroyer = null;
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
};
|
||||
|
||||
exports.ShaderEditorPanel = ShaderEditorPanel;
|
||||
|
||||
ShaderEditorPanel.prototype = {
|
||||
open: function() {
|
||||
let targetPromise;
|
||||
|
||||
// Local debugging needs to make the target remote.
|
||||
if (!this.target.isRemote) {
|
||||
targetPromise = this.target.makeRemote();
|
||||
} else {
|
||||
targetPromise = promise.resolve(this.target);
|
||||
}
|
||||
|
||||
return targetPromise
|
||||
.then(() => {
|
||||
this.panelWin.gTarget = this.target;
|
||||
this.panelWin.gFront = new WebGLFront(this.target.client, this.target.form);
|
||||
return this.panelWin.startupShaderEditor();
|
||||
})
|
||||
.then(() => {
|
||||
this.isReady = true;
|
||||
this.emit("ready");
|
||||
return this;
|
||||
})
|
||||
.then(null, function onError(aReason) {
|
||||
Cu.reportError("ShaderEditorPanel open failed. " +
|
||||
aReason.error + ": " + aReason.message);
|
||||
});
|
||||
},
|
||||
|
||||
// DevToolPanel API
|
||||
|
||||
get target() this._toolbox.target,
|
||||
|
||||
destroy: function() {
|
||||
// Make sure this panel is not already destroyed.
|
||||
if (this._destroyer) {
|
||||
return this._destroyer;
|
||||
}
|
||||
|
||||
return this._destroyer = this.panelWin.shutdownShaderEditor().then(() => {
|
||||
this.emit("destroyed");
|
||||
});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,396 @@
|
|||
/* 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 { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm");
|
||||
Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
const promise = require("sdk/core/promise");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const Editor = require("devtools/sourceeditor/editor");
|
||||
|
||||
// The panel's window global is an EventEmitter firing the following events:
|
||||
const EVENTS = {
|
||||
// When the vertex and fragment sources were shown in the editor.
|
||||
SOURCES_SHOWN: "ShaderEditor:SourcesShown",
|
||||
// When a shader's source was edited and compiled via the editor.
|
||||
SHADER_COMPILED: "ShaderEditor:ShaderCompiled"
|
||||
};
|
||||
|
||||
const STRINGS_URI = "chrome://browser/locale/devtools/shadereditor.properties"
|
||||
const HIGHLIGHT_COLOR = [1, 0, 0, 1];
|
||||
const BLACKBOX_COLOR = [0, 0, 0, 0];
|
||||
const TYPING_MAX_DELAY = 500;
|
||||
const SHADERS_AUTOGROW_ITEMS = 4;
|
||||
const DEFAULT_EDITOR_CONFIG = {
|
||||
mode: Editor.modes.text,
|
||||
lineNumbers: true,
|
||||
showAnnotationRuler: true
|
||||
};
|
||||
|
||||
/**
|
||||
* The current target and the WebGL Editor front, set by this tool's host.
|
||||
*/
|
||||
let gTarget, gFront;
|
||||
|
||||
/**
|
||||
* Initializes the shader editor controller and views.
|
||||
*/
|
||||
function startupShaderEditor() {
|
||||
return promise.all([
|
||||
EventsHandler.initialize(),
|
||||
ShadersListView.initialize(),
|
||||
ShadersEditorsView.initialize()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the shader editor controller and views.
|
||||
*/
|
||||
function shutdownShaderEditor() {
|
||||
return promise.all([
|
||||
EventsHandler.destroy(),
|
||||
ShadersListView.destroy(),
|
||||
ShadersEditorsView.destroy()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions handling target-related lifetime events.
|
||||
*/
|
||||
let EventsHandler = {
|
||||
/**
|
||||
* Listen for events emitted by the current tab target.
|
||||
*/
|
||||
initialize: function() {
|
||||
this._onWillNavigate = this._onWillNavigate.bind(this);
|
||||
this._onProgramLinked = this._onProgramLinked.bind(this);
|
||||
gTarget.on("will-navigate", this._onWillNavigate);
|
||||
gFront.on("program-linked", this._onProgramLinked);
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove events emitted by the current tab target.
|
||||
*/
|
||||
destroy: function() {
|
||||
gTarget.off("will-navigate", this._onWillNavigate);
|
||||
gFront.off("program-linked", this._onProgramLinked);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called for each location change in the debugged tab.
|
||||
*/
|
||||
_onWillNavigate: function() {
|
||||
gFront.setup();
|
||||
|
||||
ShadersListView.empty();
|
||||
ShadersEditorsView.setText({ vs: "", fs: "" });
|
||||
$("#reload-notice").hidden = true;
|
||||
$("#waiting-notice").hidden = false;
|
||||
$("#content").hidden = true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called every time a program was linked in the debugged tab.
|
||||
*/
|
||||
_onProgramLinked: function(programActor) {
|
||||
$("#waiting-notice").hidden = true;
|
||||
$("#reload-notice").hidden = true;
|
||||
$("#content").hidden = false;
|
||||
ShadersListView.addProgram(programActor);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Functions handling the sources UI.
|
||||
*/
|
||||
let ShadersListView = Heritage.extend(WidgetMethods, {
|
||||
/**
|
||||
* Initialization function, called when the tool is started.
|
||||
*/
|
||||
initialize: function() {
|
||||
this.widget = new SideMenuWidget(this._pane = $("#shaders-pane"), {
|
||||
showArrows: true,
|
||||
showItemCheckboxes: true
|
||||
});
|
||||
|
||||
this._onShaderSelect = this._onShaderSelect.bind(this);
|
||||
this._onShaderCheck = this._onShaderCheck.bind(this);
|
||||
this._onShaderMouseEnter = this._onShaderMouseEnter.bind(this);
|
||||
this._onShaderMouseLeave = this._onShaderMouseLeave.bind(this);
|
||||
|
||||
this.widget.addEventListener("select", this._onShaderSelect, false);
|
||||
this.widget.addEventListener("check", this._onShaderCheck, false);
|
||||
this.widget.addEventListener("mouseenter", this._onShaderMouseEnter, true);
|
||||
this.widget.addEventListener("mouseleave", this._onShaderMouseLeave, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Destruction function, called when the tool is closed.
|
||||
*/
|
||||
destroy: function() {
|
||||
this.widget.removeEventListener("select", this._onShaderSelect, false);
|
||||
this.widget.removeEventListener("check", this._onShaderCheck, false);
|
||||
this.widget.removeEventListener("mouseenter", this._onShaderMouseEnter, true);
|
||||
this.widget.removeEventListener("mouseleave", this._onShaderMouseLeave, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a program to this programs container.
|
||||
*
|
||||
* @param object programActor
|
||||
* The program actor coming from the active thread.
|
||||
*/
|
||||
addProgram: function(programActor) {
|
||||
// Currently, there's no good way of differentiating between programs
|
||||
// in a way that helps humans. It will be a good idea to implement a
|
||||
// standard of allowing debuggees to add some identifiable metadata to their
|
||||
// program sources or instances.
|
||||
let label = L10N.getFormatStr("shadersList.programLabel", this.itemCount);
|
||||
|
||||
// Append a program item to this container.
|
||||
this.push([label, ""], {
|
||||
index: -1, /* specifies on which position should the item be appended */
|
||||
relaxed: true, /* this container should allow dupes & degenerates */
|
||||
attachment: {
|
||||
programActor: programActor,
|
||||
checkboxState: true,
|
||||
checkboxTooltip: L10N.getStr("shadersList.blackboxLabel")
|
||||
}
|
||||
});
|
||||
|
||||
// Make sure there's always a selected item available.
|
||||
if (!this.selectedItem) {
|
||||
this.selectedIndex = 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The select listener for the sources container.
|
||||
*/
|
||||
_onShaderSelect: function({ detail: sourceItem }) {
|
||||
if (!sourceItem) {
|
||||
return;
|
||||
}
|
||||
// The container is not empty and an actual item was selected.
|
||||
let attachment = sourceItem.attachment;
|
||||
|
||||
function getShaders() {
|
||||
return promise.all([
|
||||
attachment.vs || (attachment.vs = attachment.programActor.getVertexShader()),
|
||||
attachment.fs || (attachment.fs = attachment.programActor.getFragmentShader())
|
||||
]);
|
||||
}
|
||||
function getSources([vertexShaderActor, fragmentShaderActor]) {
|
||||
return promise.all([
|
||||
vertexShaderActor.getText(),
|
||||
fragmentShaderActor.getText()
|
||||
]);
|
||||
}
|
||||
function showSources([vertexShaderText, fragmentShaderText]) {
|
||||
ShadersEditorsView.setText({
|
||||
vs: vertexShaderText,
|
||||
fs: fragmentShaderText
|
||||
});
|
||||
}
|
||||
|
||||
getShaders().then(getSources).then(showSources).then(null, Cu.reportError);
|
||||
},
|
||||
|
||||
/**
|
||||
* The check listener for the sources container.
|
||||
*/
|
||||
_onShaderCheck: function({ detail: { checked }, target }) {
|
||||
let sourceItem = this.getItemForElement(target);
|
||||
let attachment = sourceItem.attachment;
|
||||
attachment.isBlackBoxed = !checked;
|
||||
attachment.programActor[checked ? "unhighlight" : "highlight"](BLACKBOX_COLOR);
|
||||
},
|
||||
|
||||
/**
|
||||
* The mouseenter listener for the sources container.
|
||||
*/
|
||||
_onShaderMouseEnter: function(e) {
|
||||
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
|
||||
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
|
||||
sourceItem.attachment.programActor.highlight(HIGHLIGHT_COLOR);
|
||||
|
||||
if (e instanceof Event) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The mouseleave listener for the sources container.
|
||||
*/
|
||||
_onShaderMouseLeave: function(e) {
|
||||
let sourceItem = this.getItemForElement(e.target, { noSiblings: true });
|
||||
if (sourceItem && !sourceItem.attachment.isBlackBoxed) {
|
||||
sourceItem.attachment.programActor.unhighlight();
|
||||
|
||||
if (e instanceof Event) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Functions handling the editors displaying the vertex and fragment shaders.
|
||||
*/
|
||||
let ShadersEditorsView = {
|
||||
/**
|
||||
* Initialization function, called when the tool is started.
|
||||
*/
|
||||
initialize: function() {
|
||||
XPCOMUtils.defineLazyGetter(this, "_editorPromises", () => new Map());
|
||||
this._vsFocused = this._onFocused.bind(this, "vs", "fs");
|
||||
this._fsFocused = this._onFocused.bind(this, "fs", "vs");
|
||||
this._vsChanged = this._onChanged.bind(this, "vs");
|
||||
this._fsChanged = this._onChanged.bind(this, "fs");
|
||||
},
|
||||
|
||||
/**
|
||||
* Destruction function, called when the tool is closed.
|
||||
*/
|
||||
destroy: function() {
|
||||
this._toggleListeners("off");
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the text displayed in the vertex and fragment shader editors.
|
||||
*
|
||||
* @param object sources
|
||||
* An object containing the following properties
|
||||
* - vs: the vertex shader source code
|
||||
* - fs: the fragment shader source code
|
||||
*/
|
||||
setText: function(sources) {
|
||||
function setTextAndClearHistory(editor, text) {
|
||||
editor.setText(text);
|
||||
editor.clearHistory();
|
||||
}
|
||||
|
||||
this._toggleListeners("off");
|
||||
this._getEditor("vs").then(e => setTextAndClearHistory(e, sources.vs));
|
||||
this._getEditor("fs").then(e => setTextAndClearHistory(e, sources.fs));
|
||||
this._toggleListeners("on");
|
||||
|
||||
window.emit(EVENTS.SOURCES_SHOWN, sources);
|
||||
},
|
||||
|
||||
/**
|
||||
* Lazily initializes and returns a promise for an Editor instance.
|
||||
*
|
||||
* @param string type
|
||||
* Specifies for which shader type should an editor be retrieved,
|
||||
* either are "vs" for a vertex, or "fs" for a fragment shader.
|
||||
*/
|
||||
_getEditor: function(type) {
|
||||
if ($("#content").hidden) {
|
||||
return promise.reject(null);
|
||||
}
|
||||
if (this._editorPromises.has(type)) {
|
||||
return this._editorPromises.get(type);
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
this._editorPromises.set(type, deferred.promise);
|
||||
|
||||
// Initialize the source editor and store the newly created instance
|
||||
// in the ether of a resolved promise's value.
|
||||
let parent = $("#" + type +"-editor");
|
||||
let editor = new Editor(DEFAULT_EDITOR_CONFIG);
|
||||
editor.appendTo(parent).then(() => deferred.resolve(editor));
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles all the event listeners for the editors either on or off.
|
||||
*
|
||||
* @param string flag
|
||||
* Either "on" to enable the event listeners, "off" to disable them.
|
||||
*/
|
||||
_toggleListeners: function(flag) {
|
||||
["vs", "fs"].forEach(type => {
|
||||
this._getEditor(type).then(editor => {
|
||||
editor[flag]("focus", this["_" + type + "Focused"]);
|
||||
editor[flag]("change", this["_" + type + "Changed"]);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* The focus listener for a source editor.
|
||||
*
|
||||
* @param string focused
|
||||
* The corresponding shader type for the focused editor (e.g. "vs").
|
||||
* @param string focused
|
||||
* The corresponding shader type for the other editor (e.g. "fs").
|
||||
*/
|
||||
_onFocused: function(focused, unfocused) {
|
||||
$("#" + focused + "-editor-label").setAttribute("selected", "");
|
||||
$("#" + unfocused + "-editor-label").removeAttribute("selected");
|
||||
},
|
||||
|
||||
/**
|
||||
* The change listener for a source editor.
|
||||
*
|
||||
* @param string type
|
||||
* The corresponding shader type for the focused editor (e.g. "vs").
|
||||
*/
|
||||
_onChanged: function(type) {
|
||||
setNamedTimeout("gl-typed", TYPING_MAX_DELAY, () => this._doCompile(type));
|
||||
},
|
||||
|
||||
/**
|
||||
* Recompiles the source code for the shader being edited.
|
||||
* This function is fired at a certain delay after the user stops typing.
|
||||
*
|
||||
* @param string type
|
||||
* The corresponding shader type for the focused editor (e.g. "vs").
|
||||
*/
|
||||
_doCompile: function(type) {
|
||||
Task.spawn(function() {
|
||||
let editor = yield this._getEditor(type);
|
||||
let shaderActor = yield ShadersListView.selectedAttachment[type];
|
||||
|
||||
try {
|
||||
yield shaderActor.compile(editor.getText());
|
||||
window.emit(EVENTS.SHADER_COMPILED, null);
|
||||
// TODO: remove error gutter markers, after bug 919709 lands.
|
||||
} catch (error) {
|
||||
window.emit(EVENTS.SHADER_COMPILED, error);
|
||||
// TODO: add error gutter markers, after bug 919709 lands.
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Localization convenience methods.
|
||||
*/
|
||||
let L10N = new ViewHelpers.L10N(STRINGS_URI);
|
||||
|
||||
/**
|
||||
* Convenient way of emitting events from the panel window.
|
||||
*/
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
/**
|
||||
* DOM query helper.
|
||||
*/
|
||||
function $(selector, target = document) target.querySelector(selector);
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/common.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/widgets.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/skin/devtools/shadereditor.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/devtools/widgets.css" type="text/css"?>
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % debuggerDTD SYSTEM "chrome://browser/locale/devtools/shadereditor.dtd">
|
||||
%debuggerDTD;
|
||||
]>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="shadereditor.js"/>
|
||||
|
||||
<vbox id="body" flex="1">
|
||||
<hbox id="reload-notice"
|
||||
class="notice-container"
|
||||
align="center"
|
||||
pack="center"
|
||||
flex="1">
|
||||
<button id="requests-menu-reload-notice-button"
|
||||
class="devtools-toolbarbutton"
|
||||
label="&shaderEditorUI.reloadNotice1;"
|
||||
oncommand="gFront.setup();"/>
|
||||
<label id="requests-menu-reload-notice-label"
|
||||
class="plain"
|
||||
value="&shaderEditorUI.reloadNotice2;"/>
|
||||
</hbox>
|
||||
<hbox id="waiting-notice"
|
||||
class="notice-container"
|
||||
align="center"
|
||||
pack="center"
|
||||
flex="1"
|
||||
hidden="true">
|
||||
<label id="requests-menu-waiting-notice-label"
|
||||
class="plain"
|
||||
value="&shaderEditorUI.emptyNotice;"/>
|
||||
</hbox>
|
||||
|
||||
<hbox id="content" flex="1" hidden="true">
|
||||
<vbox id="shaders-pane"/>
|
||||
<splitter class="devtools-side-splitter"/>
|
||||
<hbox id="shaders-editors" flex="1">
|
||||
<vbox flex="1">
|
||||
<vbox id="vs-editor" flex="1"/>
|
||||
<label id="vs-editor-label"
|
||||
class="plain editor-label"
|
||||
value="&shaderEditorUI.vertexShader;"/>
|
||||
</vbox>
|
||||
<splitter id="editors-splitter" class="devtools-side-splitter"/>
|
||||
<vbox flex="1">
|
||||
<vbox id="fs-editor" flex="1"/>
|
||||
<label id="fs-editor-label"
|
||||
class="plain editor-label"
|
||||
value="&shaderEditorUI.fragmentShader;"/>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
|
||||
</window>
|
|
@ -0,0 +1,33 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
doc_multiple-contexts.html
|
||||
doc_shader-order.html
|
||||
doc_simple-canvas.html
|
||||
head.js
|
||||
|
||||
[browser_se_aaa_run_first_leaktest.js]
|
||||
[browser_se_editors-contents.js]
|
||||
[browser_se_editors-lazy-init.js]
|
||||
[browser_se_first-run.js]
|
||||
[browser_se_navigation.js]
|
||||
[browser_se_programs-blackbox.js]
|
||||
[browser_se_programs-cache.js]
|
||||
[browser_se_programs-highlight.js]
|
||||
[browser_se_programs-list.js]
|
||||
[browser_se_shaders-edit-01.js]
|
||||
[browser_se_shaders-edit-02.js]
|
||||
[browser_se_shaders-edit-03.js]
|
||||
[browser_webgl-actor-test-01.js]
|
||||
[browser_webgl-actor-test-02.js]
|
||||
[browser_webgl-actor-test-03.js]
|
||||
[browser_webgl-actor-test-04.js]
|
||||
[browser_webgl-actor-test-05.js]
|
||||
[browser_webgl-actor-test-06.js]
|
||||
[browser_webgl-actor-test-07.js]
|
||||
[browser_webgl-actor-test-08.js]
|
||||
[browser_webgl-actor-test-09.js]
|
||||
[browser_webgl-actor-test-10.js]
|
||||
[browser_webgl-actor-test-11.js]
|
||||
[browser_webgl-actor-test-12.js]
|
||||
[browser_webgl-actor-test-13.js]
|
||||
[browser_webgl-actor-test-14.js]
|
|
@ -0,0 +1,18 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the shader editor leaks on initialization and sudden destruction.
|
||||
* You can also use this initialization format as a template for other tests.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
|
||||
ok(target, "Should have a target available.");
|
||||
ok(debuggee, "Should have a debuggee available.");
|
||||
ok(panel, "Should have a panel available.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the editors contain the correct text when a program
|
||||
* becomes available.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
is(vsEditor.getText().indexOf("gl_Position"), 170,
|
||||
"The vertex shader editor contains the correct text.");
|
||||
is(fsEditor.getText().indexOf("gl_FragColor"), 97,
|
||||
"The fragment shader editor contains the correct text.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if source editors are lazily initialized.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
try {
|
||||
yield ShadersEditorsView._getEditor("vs");
|
||||
ok(false, "The promise for a vertex shader editor should be rejected.");
|
||||
} catch (e) {
|
||||
ok(true, "The vertex shader editors wasn't initialized.");
|
||||
}
|
||||
|
||||
try {
|
||||
yield ShadersEditorsView._getEditor("fs");
|
||||
ok(false, "The promise for a fragment shader editor should be rejected.");
|
||||
} catch (e) {
|
||||
ok(true, "The fragment shader editors wasn't initialized.");
|
||||
}
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
ok(vsEditor, "A vertex shader editor was initialized.");
|
||||
ok(fsEditor, "A fragment shader editor was initialized.");
|
||||
|
||||
isnot(vsEditor, fsEditor,
|
||||
"The vertex shader editor is distinct from the fragment shader editor.");
|
||||
|
||||
let vsEditor2 = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor2 = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
is(vsEditor, vsEditor2,
|
||||
"The vertex shader editor instances are cached.");
|
||||
is(fsEditor, fsEditor2,
|
||||
"The fragment shader editor instances are cached.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the shader editor shows the appropriate UI when opened.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, $ } = panel.panelWin;
|
||||
|
||||
is($("#reload-notice").hidden, false,
|
||||
"The 'reload this page' notice should initially be visible.");
|
||||
is($("#waiting-notice").hidden, true,
|
||||
"The 'waiting for a WebGL context' notice should initially be hidden.");
|
||||
is($("#content").hidden, true,
|
||||
"The tool's content should initially be hidden.");
|
||||
|
||||
let navigating = once(target, "will-navigate");
|
||||
let linked = once(gFront, "program-linked");
|
||||
reload(target);
|
||||
|
||||
yield navigating;
|
||||
|
||||
is($("#reload-notice").hidden, true,
|
||||
"The 'reload this page' notice should be hidden when navigating.");
|
||||
is($("#waiting-notice").hidden, false,
|
||||
"The 'waiting for a WebGL context' notice should be visible when navigating.");
|
||||
is($("#content").hidden, true,
|
||||
"The tool's content should still be hidden.");
|
||||
|
||||
yield linked;
|
||||
|
||||
is($("#reload-notice").hidden, true,
|
||||
"The 'reload this page' notice should be hidden after linking.");
|
||||
is($("#waiting-notice").hidden, true,
|
||||
"The 'waiting for a WebGL context' notice should be hidden after linking.");
|
||||
is($("#content").hidden, false,
|
||||
"The tool's content should not be hidden anymore.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests target navigations are handled correctly in the UI.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, $, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
|
||||
is($("#reload-notice").hidden, true,
|
||||
"The 'reload this page' notice should be hidden after linking.");
|
||||
is($("#waiting-notice").hidden, true,
|
||||
"The 'waiting for a WebGL context' notice should be visible after linking.");
|
||||
is($("#content").hidden, false,
|
||||
"The tool's content should not be hidden anymore.");
|
||||
|
||||
is(ShadersListView.itemCount, 1,
|
||||
"The shaders list contains one entry.");
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[0],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct index selected.");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
is(vsEditor.getText().indexOf("gl_Position"), 170,
|
||||
"The vertex shader editor contains the correct text.");
|
||||
is(fsEditor.getText().indexOf("gl_FragColor"), 97,
|
||||
"The fragment shader editor contains the correct text.");
|
||||
|
||||
let navigating = once(target, "will-navigate");
|
||||
let navigated = once(target, "will-navigate");
|
||||
navigate(target, "about:blank");
|
||||
|
||||
yield navigating;
|
||||
|
||||
is($("#reload-notice").hidden, true,
|
||||
"The 'reload this page' notice should be hidden while navigating.");
|
||||
is($("#waiting-notice").hidden, false,
|
||||
"The 'waiting for a WebGL context' notice should be visible while navigating.");
|
||||
is($("#content").hidden, true,
|
||||
"The tool's content should be hidden now that there's no WebGL content.");
|
||||
|
||||
is(ShadersListView.itemCount, 0,
|
||||
"The shaders list should be empty.");
|
||||
is(ShadersListView.selectedItem, null,
|
||||
"The shaders list has no correct item.");
|
||||
is(ShadersListView.selectedIndex, -1,
|
||||
"The shaders list has a negative index.");
|
||||
|
||||
try {
|
||||
yield ShadersEditorsView._getEditor("vs");
|
||||
ok(false, "The promise for a vertex shader editor should be rejected.");
|
||||
} catch (e) {
|
||||
ok(true, "The vertex shader editors wasn't initialized.");
|
||||
}
|
||||
|
||||
try {
|
||||
yield ShadersEditorsView._getEditor("fs");
|
||||
ok(false, "The promise for a fragment shader editor should be rejected.");
|
||||
} catch (e) {
|
||||
ok(true, "The fragment shader editors wasn't initialized.");
|
||||
}
|
||||
|
||||
yield navigated;
|
||||
|
||||
is($("#reload-notice").hidden, true,
|
||||
"The 'reload this page' notice should still be hidden after navigating.");
|
||||
is($("#waiting-notice").hidden, false,
|
||||
"The 'waiting for a WebGL context' notice should still be visible after navigating.");
|
||||
is($("#content").hidden, true,
|
||||
"The tool's content should be still hidden since there's no WebGL content.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if blackboxing a program works properly.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
|
||||
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
once(panel.panelWin, EVENTS.SHADER_COMPILED).then(() => {
|
||||
ok(false, "No shaders should be publicly compiled during this test.");
|
||||
});
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
vsEditor.once("change", () => {
|
||||
ok(false, "The vertex shader source was unexpectedly changed.");
|
||||
});
|
||||
fsEditor.once("change", () => {
|
||||
ok(false, "The fragment shader source was unexpectedly changed.");
|
||||
});
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN).then(() => {
|
||||
ok(false, "No sources should be changed form this point onward.");
|
||||
});
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
|
||||
ok(!ShadersListView.selectedAttachment.isBlackBoxed,
|
||||
"The first program should not be blackboxed yet.");
|
||||
is(getBlackBoxCheckbox(panel, 0).checked, true,
|
||||
"The first blackbox checkbox should be initially checked.");
|
||||
ok(!ShadersListView.attachments[1].isBlackBoxed,
|
||||
"The second program should not be blackboxed yet.");
|
||||
is(getBlackBoxCheckbox(panel, 1).checked, true,
|
||||
"The second blackbox checkbox should be initially checked.");
|
||||
|
||||
getBlackBoxCheckbox(panel, 0).click();
|
||||
|
||||
ok(ShadersListView.selectedAttachment.isBlackBoxed,
|
||||
"The first program should now be blackboxed.");
|
||||
is(getBlackBoxCheckbox(panel, 0).checked, false,
|
||||
"The first blackbox checkbox should now be unchecked.");
|
||||
ok(!ShadersListView.attachments[1].isBlackBoxed,
|
||||
"The second program should still not be blackboxed.");
|
||||
is(getBlackBoxCheckbox(panel, 1).checked, true,
|
||||
"The second blackbox checkbox should still be checked.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The first program was correctly blackboxed.");
|
||||
|
||||
getBlackBoxCheckbox(panel, 1).click();
|
||||
|
||||
ok(ShadersListView.selectedAttachment.isBlackBoxed,
|
||||
"The first program should still be blackboxed.");
|
||||
is(getBlackBoxCheckbox(panel, 0).checked, false,
|
||||
"The first blackbox checkbox should still be unchecked.");
|
||||
ok(ShadersListView.attachments[1].isBlackBoxed,
|
||||
"The second program should now be blackboxed.");
|
||||
is(getBlackBoxCheckbox(panel, 1).checked, false,
|
||||
"The second blackbox checkbox should now be unchecked.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
ok(true, "The second program was correctly blackboxed.");
|
||||
|
||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
ok(true, "Highlighting didn't work while blackboxed (1).");
|
||||
|
||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
|
||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
ok(true, "Highlighting didn't work while blackboxed (2).");
|
||||
|
||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 0 }, true, "#canvas2");
|
||||
ok(true, "Highlighting didn't work while blackboxed (3).");
|
||||
|
||||
getBlackBoxCheckbox(panel, 0).click();
|
||||
getBlackBoxCheckbox(panel, 1).click();
|
||||
|
||||
ok(!ShadersListView.selectedAttachment.isBlackBoxed,
|
||||
"The first program should now be unblackboxed.");
|
||||
is(getBlackBoxCheckbox(panel, 0).checked, true,
|
||||
"The first blackbox checkbox should now be rechecked.");
|
||||
ok(!ShadersListView.attachments[1].isBlackBoxed,
|
||||
"The second program should now be unblackboxed.");
|
||||
is(getBlackBoxCheckbox(panel, 1).checked, true,
|
||||
"The second blackbox checkbox should now be rechecked.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two programs were correctly unblackboxed.");
|
||||
|
||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The first program was correctly highlighted.");
|
||||
|
||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
|
||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The second program was correctly highlighted.");
|
||||
|
||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two programs were correctly unhighlighted.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function getItemLabel(aPanel, aIndex) {
|
||||
return aPanel.panelWin.document.querySelectorAll(
|
||||
".side-menu-widget-item-label")[aIndex];
|
||||
}
|
||||
|
||||
function getBlackBoxCheckbox(aPanel, aIndex) {
|
||||
return aPanel.panelWin.document.querySelectorAll(
|
||||
".side-menu-widget-item-checkbox")[aIndex];
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that program and shader actors are cached in the frontend.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
|
||||
let { gFront, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
let programActor = yield once(gFront, "program-linked");
|
||||
let programItem = ShadersListView.selectedItem;
|
||||
|
||||
is(programItem.attachment.programActor, programActor,
|
||||
"The correct program actor is cached for the selected item.");
|
||||
|
||||
is((yield programActor.getVertexShader()),
|
||||
(yield programItem.attachment.vs),
|
||||
"The cached vertex shader promise returns the correct actor.");
|
||||
|
||||
is((yield programActor.getFragmentShader()),
|
||||
(yield programItem.attachment.fs),
|
||||
"The cached fragment shader promise returns the correct actor.");
|
||||
|
||||
is((yield (yield programActor.getVertexShader()).getText()),
|
||||
(yield (yield ShadersEditorsView._getEditor("vs")).getText()),
|
||||
"The cached vertex shader promise returns the correct text.");
|
||||
|
||||
is((yield (yield programActor.getFragmentShader()).getText()),
|
||||
(yield (yield ShadersEditorsView._getEditor("fs")).getText()),
|
||||
"The cached fragment shader promise returns the correct text.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if highlighting a program works properly.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
|
||||
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
once(panel.panelWin, EVENTS.SHADER_COMPILED).then(() => {
|
||||
ok(false, "No shaders should be publicly compiled during this test.");
|
||||
});
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
vsEditor.once("change", () => {
|
||||
ok(false, "The vertex shader source was unexpectedly changed.");
|
||||
});
|
||||
fsEditor.once("change", () => {
|
||||
ok(false, "The fragment shader source was unexpectedly changed.");
|
||||
});
|
||||
once(panel.panelWin, EVENTS.SOURCES_SHOWN).then(() => {
|
||||
ok(false, "No sources should be changed form this point onward.");
|
||||
});
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
|
||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 0) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The first program was correctly highlighted.");
|
||||
|
||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 0) });
|
||||
ShadersListView._onShaderMouseEnter({ target: getItemLabel(panel, 1) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The second program was correctly highlighted.");
|
||||
|
||||
ShadersListView._onShaderMouseLeave({ target: getItemLabel(panel, 1) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two programs were correctly unhighlighted.");
|
||||
|
||||
ShadersListView._onShaderMouseEnter({ target: getBlackBoxCheckbox(panel, 0) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two programs were left unchanged after hovering a blackbox checkbox.");
|
||||
|
||||
ShadersListView._onShaderMouseLeave({ target: getBlackBoxCheckbox(panel, 0) });
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two programs were left unchanged after unhovering a blackbox checkbox.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function getItemLabel(aPanel, aIndex) {
|
||||
return aPanel.panelWin.document.querySelectorAll(
|
||||
".side-menu-widget-item-label")[aIndex];
|
||||
}
|
||||
|
||||
function getBlackBoxCheckbox(aPanel, aIndex) {
|
||||
return aPanel.panelWin.document.querySelectorAll(
|
||||
".side-menu-widget-item-checkbox")[aIndex];
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the programs list contains an entry after vertex and fragment
|
||||
* shaders are linked.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
|
||||
let { gFront, EVENTS, L10N, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
is(ShadersListView.itemCount, 0,
|
||||
"The shaders list should initially be empty.");
|
||||
is(ShadersListView.selectedItem, null,
|
||||
"The shaders list has no selected item.");
|
||||
is(ShadersListView.selectedIndex, -1,
|
||||
"The shaders list has a negative index.");
|
||||
|
||||
reload(target);
|
||||
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
is(ShadersListView.itemCount, 1,
|
||||
"The shaders list contains one entry.");
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[0],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct index selected.");
|
||||
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
is(ShadersListView.itemCount, 2,
|
||||
"The shaders list contains two entries.");
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[0],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The shaders list has a correct index selected.");
|
||||
|
||||
is(ShadersListView.labels[0], L10N.getFormatStr("shadersList.programLabel", 0),
|
||||
"The correct first label is shown in the shaders list.");
|
||||
is(ShadersListView.labels[1], L10N.getFormatStr("shadersList.programLabel", 1),
|
||||
"The correct second label is shown in the shaders list.");
|
||||
|
||||
let vertexShader = yield firstProgramActor.getVertexShader();
|
||||
let fragmentShader = yield firstProgramActor.getFragmentShader();
|
||||
let vertSource = yield vertexShader.getText();
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
is(vertSource, vsEditor.getText(),
|
||||
"The vertex shader editor contains the correct text.");
|
||||
is(fragSource, fsEditor.getText(),
|
||||
"The vertex shader editor contains the correct text.");
|
||||
|
||||
let compiled = once(panel.panelWin, EVENTS.SHADER_COMPILED).then(() => {
|
||||
ok(false, "Selecting a different program shouldn't recompile its shaders.");
|
||||
});
|
||||
|
||||
let shown = once(panel.panelWin, EVENTS.SOURCES_SHOWN).then(() => {
|
||||
ok(true, "The vertex and fragment sources have changed in the editors.");
|
||||
});
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, ShadersListView.items[1].target);
|
||||
yield shown;
|
||||
|
||||
is(ShadersListView.selectedItem, ShadersListView.items[1],
|
||||
"The shaders list has a correct item selected.");
|
||||
is(ShadersListView.selectedIndex, 1,
|
||||
"The shaders list has a correct index selected.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if editing a vertex and a fragment shader works properly.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, $, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
is(vsEditor.getText().indexOf("gl_Position"), 170,
|
||||
"The vertex shader editor contains the correct text.");
|
||||
is(fsEditor.getText().indexOf("gl_FragColor"), 97,
|
||||
"The fragment shader editor contains the correct text.");
|
||||
|
||||
is($("#vs-editor-label").hasAttribute("selected"), false,
|
||||
"The vertex shader editor shouldn't be initially selected.");
|
||||
is($("#fs-editor-label").hasAttribute("selected"), false,
|
||||
"The vertex shader editor shouldn't be initially selected.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 191, g: 64, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
|
||||
vsEditor.focus();
|
||||
|
||||
is($("#vs-editor-label").hasAttribute("selected"), true,
|
||||
"The vertex shader editor should now be selected.");
|
||||
is($("#fs-editor-label").hasAttribute("selected"), false,
|
||||
"The vertex shader editor shouldn't still not be selected.");
|
||||
|
||||
vsEditor.replaceText("2.0", { line: 7, ch: 44 }, { line: 7, ch: 47 });
|
||||
yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
ok(true, "Vertex shader was changed.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
|
||||
ok(true, "The vertex shader was recompiled successfully.");
|
||||
|
||||
fsEditor.focus();
|
||||
|
||||
is($("#vs-editor-label").hasAttribute("selected"), false,
|
||||
"The vertex shader editor should now be deselected.");
|
||||
is($("#fs-editor-label").hasAttribute("selected"), true,
|
||||
"The vertex shader editor should now be selected.");
|
||||
|
||||
fsEditor.replaceText("0.5", { line: 5, ch: 44 }, { line: 5, ch: 47 });
|
||||
yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
ok(true, "Fragment shader was changed.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 255, g: 0, b: 0, a: 127 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
|
||||
ok(true, "The fragment shader was recompiled successfully.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if compile or linkage errors are emitted when a shader source
|
||||
* gets malformed after being edited.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
|
||||
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
yield once(gFront, "program-linked");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
ok(error,
|
||||
"The new vertex shader source was compiled with errors.");
|
||||
is(error.compile, "",
|
||||
"The compilation status should be empty.");
|
||||
isnot(error.link, "",
|
||||
"The linkage status should not be empty.");
|
||||
is(error.link.split("ERROR").length - 1, 2,
|
||||
"The linkage status contains two errors.");
|
||||
ok(error.link.contains("ERROR: 0:8: 'constructor'"),
|
||||
"A constructor error is contained in the linkage status.");
|
||||
ok(error.link.contains("ERROR: 0:8: 'assign'"),
|
||||
"An assignment error is contained in the linkage status.");
|
||||
|
||||
fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
ok(error,
|
||||
"The new fragment shader source was compiled with errors.");
|
||||
is(error.compile, "",
|
||||
"The compilation status should be empty.");
|
||||
isnot(error.link, "",
|
||||
"The linkage status should not be empty.");
|
||||
is(error.link.split("ERROR").length - 1, 1,
|
||||
"The linkage status contains one error.");
|
||||
ok(error.link.contains("ERROR: 0:6: 'constructor'"),
|
||||
"A constructor error is contained in the linkage status.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
|
||||
vsEditor.replaceText("vec4", { line: 7, ch: 22 }, { line: 7, ch: 26 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
ok(!error, "The new vertex shader source was compiled successfully.");
|
||||
|
||||
fsEditor.replaceText("vec3", { line: 2, ch: 14 }, { line: 2, ch: 18 });
|
||||
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
ok(!error, "The new fragment shader source was compiled successfully.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
|
||||
return deferred.promise;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if editing a vertex and a fragment shader works properly.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
|
||||
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
|
||||
|
||||
reload(target);
|
||||
let firstProgramActor = yield once(gFront, "program-linked");
|
||||
let secondProgramActor = yield once(gFront, "program-linked");
|
||||
|
||||
let vsEditor = yield ShadersEditorsView._getEditor("vs");
|
||||
let fsEditor = yield ShadersEditorsView._getEditor("fs");
|
||||
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The first program is currently selected.");
|
||||
is(vsEditor.getText().indexOf("1);"), 136,
|
||||
"The vertex shader editor contains the correct initial text (1).");
|
||||
is(fsEditor.getText().indexOf("1);"), 117,
|
||||
"The fragment shader editor contains the correct initial text (1).");
|
||||
is(vsEditor.getText().indexOf("2.);"), -1,
|
||||
"The vertex shader editor contains the correct initial text (2).");
|
||||
is(fsEditor.getText().indexOf(".0);"), -1,
|
||||
"The fragment shader editor contains the correct initial text (2).");
|
||||
|
||||
vsEditor.replaceText("2.", { line: 5, ch: 44 }, { line: 5, ch: 45 });
|
||||
yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
fsEditor.replaceText(".0", { line: 5, ch: 35 }, { line: 5, ch: 37 });
|
||||
yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
|
||||
|
||||
ok(true, "Vertex and fragment shaders were changed.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 32, y: 32 }, { r: 255, g: 255, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 255, g: 255, b: 0, a: 0 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 32, y: 32 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
|
||||
ok(true, "The vertex and fragment shaders were recompiled successfully.");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, ShadersListView.items[1].target);
|
||||
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN);
|
||||
|
||||
is(ShadersListView.selectedIndex, 1,
|
||||
"The second program is currently selected.");
|
||||
is(vsEditor.getText().indexOf("1);"), 136,
|
||||
"The vertex shader editor contains the correct text (1).");
|
||||
is(fsEditor.getText().indexOf("1);"), 117,
|
||||
"The fragment shader editor contains the correct text (1).");
|
||||
is(vsEditor.getText().indexOf("2.);"), -1,
|
||||
"The vertex shader editor contains the correct text (2).");
|
||||
is(fsEditor.getText().indexOf(".0);"), -1,
|
||||
"The fragment shader editor contains the correct text (2).");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, ShadersListView.items[0].target);
|
||||
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN);
|
||||
|
||||
is(ShadersListView.selectedIndex, 0,
|
||||
"The first program is currently selected again.");
|
||||
is(vsEditor.getText().indexOf("1);"), -1,
|
||||
"The vertex shader editor contains the correct text (3).");
|
||||
is(fsEditor.getText().indexOf("1);"), -1,
|
||||
"The fragment shader editor contains the correct text (3).");
|
||||
is(vsEditor.getText().indexOf("2.);"), 136,
|
||||
"The vertex shader editor contains the correct text (4).");
|
||||
is(fsEditor.getText().indexOf(".0);"), 116,
|
||||
"The fragment shader editor contains the correct text (4).");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEvent) {
|
||||
let deferred = promise.defer();
|
||||
aTarget.once(aEvent, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if a WebGL front can be created for a remote tab target.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
|
||||
ok(target, "Should have a target available.");
|
||||
ok(debuggee, "Should have a debuggee available.");
|
||||
ok(front, "Should have a protocol front available.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if notifications about WebGL programs being linked are not sent
|
||||
* if the front wasn't set up first.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
|
||||
once(front, "program-linked").then(() => {
|
||||
ok(false, "A 'program-linked' notification shouldn't have been sent!");
|
||||
});
|
||||
|
||||
yield reload(target);
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if notifications about WebGL programs being linked are sent
|
||||
* after a target navigation.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
|
||||
let navigated = once(target, "navigate");
|
||||
let linked = once(front, "program-linked");
|
||||
|
||||
yield front.setup();
|
||||
ok(true, "The front was setup up successfully.");
|
||||
|
||||
yield navigated;
|
||||
ok(true, "Target automatically navigated when the front was set up.");
|
||||
|
||||
yield linked;
|
||||
ok(true, "A 'program-linked' notification was sent after reloading.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if a program actor is sent when WebGL programs are linked,
|
||||
* and that the corresponding vertex and fragment actors can be retrieved.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
ok(programActor,
|
||||
"A program actor was sent along with the 'program-linked' notification.")
|
||||
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
ok(programActor,
|
||||
"A vertex shader actor was retrieved from the program actor.");
|
||||
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
ok(programActor,
|
||||
"A fragment shader actor was retrieved from the program actor.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the source contents can be retrieved from the vertex and fragment
|
||||
* shader actors.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
let vertSource = yield vertexShader.getText();
|
||||
ok(vertSource.contains("gl_Position"),
|
||||
"The correct vertex shader source was retrieved.");
|
||||
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
ok(fragSource.contains("gl_FragColor"),
|
||||
"The correct fragment shader source was retrieved.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the highlight/unhighlight operations on program actors
|
||||
* work as expected.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
yield checkShaderSource("The shader sources are correct before highlighting.");
|
||||
ok(true, "The top left pixel color was correct before highlighting.");
|
||||
|
||||
yield programActor.highlight([0, 0, 1, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
yield checkShaderSource("The shader sources are preserved after highlighting.");
|
||||
ok(true, "The top left pixel color is correct after highlighting.");
|
||||
|
||||
yield programActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
yield checkShaderSource("The shader sources are correct after unhighlighting.");
|
||||
ok(true, "The top left pixel color is correct after unhighlighting.");
|
||||
|
||||
function checkShaderSource(aMessage) {
|
||||
return Task.spawn(function() {
|
||||
let newVertexShader = yield programActor.getVertexShader();
|
||||
let newFragmentShader = yield programActor.getFragmentShader();
|
||||
is(vertexShader, newVertexShader,
|
||||
"The same vertex shader actor was retrieved.");
|
||||
is(fragmentShader, newFragmentShader,
|
||||
"The same fragment shader actor was retrieved.");
|
||||
|
||||
let vertSource = yield newVertexShader.getText();
|
||||
let fragSource = yield newFragmentShader.getText();
|
||||
ok(vertSource.contains("I'm special!") &&
|
||||
fragSource.contains("I'm also special!"), aMessage);
|
||||
});
|
||||
}
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that vertex and fragment shader sources can be changed.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 191, g: 64, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
|
||||
let vertSource = yield vertexShader.getText();
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
ok(!vertSource.contains("2.0"),
|
||||
"The vertex shader source is correct before changing it.");
|
||||
ok(!fragSource.contains("0.5"),
|
||||
"The fragment shader source is correct before changing it.");
|
||||
|
||||
let newVertSource = vertSource.replace("1.0", "2.0");
|
||||
let status = yield vertexShader.compile(newVertSource);
|
||||
ok(!status,
|
||||
"The new vertex shader source was compiled without errors.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
|
||||
let vertSource = yield vertexShader.getText();
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
ok(vertSource.contains("2.0"),
|
||||
"The vertex shader source is correct after changing it.");
|
||||
ok(!fragSource.contains("0.5"),
|
||||
"The fragment shader source is correct after changing the vertex shader.");
|
||||
|
||||
let newFragSource = fragSource.replace("1.0", "0.5");
|
||||
let status = yield fragmentShader.compile(newFragSource);
|
||||
ok(!status,
|
||||
"The new fragment shader source was compiled without errors.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 255, g: 0, b: 0, a: 127 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
|
||||
|
||||
let vertSource = yield vertexShader.getText();
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
ok(vertSource.contains("2.0"),
|
||||
"The vertex shader source is correct after changing the fragment shader.");
|
||||
ok(fragSource.contains("0.5"),
|
||||
"The fragment shader source is correct after changing it.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the rendering is updated when a varying variable is
|
||||
* changed in one shader.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
let oldVertSource = yield vertexShader.getText();
|
||||
let newVertSource = oldVertSource.replace("= aVertexColor", "= vec3(0, 0, 1)");
|
||||
let status = yield vertexShader.compile(newVertSource);
|
||||
ok(!status,
|
||||
"The new vertex shader source was compiled without errors.");
|
||||
|
||||
yield waitForFrame(debuggee);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
|
||||
let vertSource = yield vertexShader.getText();
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
ok(vertSource.contains("vFragmentColor = vec3(0, 0, 1);"),
|
||||
"The vertex shader source is correct after changing it.");
|
||||
ok(fragSource.contains("gl_FragColor = vec4(vFragmentColor, 1.0);"),
|
||||
"The fragment shader source is correct after changing the vertex shader.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that errors are properly handled when trying to compile a
|
||||
* defective shader source.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
front.setup();
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
let oldVertSource = yield vertexShader.getText();
|
||||
let newVertSource = oldVertSource.replace("vec4", "vec3");
|
||||
|
||||
try {
|
||||
yield vertexShader.compile(newVertSource);
|
||||
ok(false, "Vertex shader was compiled with a defective source!");
|
||||
} catch (error) {
|
||||
ok(error,
|
||||
"The new vertex shader source was compiled with errors.");
|
||||
is(error.compile, "",
|
||||
"The compilation status should be empty.");
|
||||
isnot(error.link, "",
|
||||
"The linkage status should not be empty.");
|
||||
is(error.link.split("ERROR").length - 1, 2,
|
||||
"The linkage status contains two errors.");
|
||||
ok(error.link.contains("ERROR: 0:8: 'constructor'"),
|
||||
"A constructor error is contained in the linkage status.");
|
||||
ok(error.link.contains("ERROR: 0:8: 'assign'"),
|
||||
"An assignment error is contained in the linkage status.");
|
||||
}
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
ok(true, "The shader was reverted to the old source.");
|
||||
|
||||
let vertSource = yield vertexShader.getText();
|
||||
ok(vertSource.contains("vec4(aVertexPosition, 1.0);"),
|
||||
"The previous correct vertex shader source was preserved.");
|
||||
|
||||
let oldFragSource = yield fragmentShader.getText();
|
||||
let newFragSource = oldFragSource.replace("vec3", "vec4");
|
||||
|
||||
try {
|
||||
yield fragmentShader.compile(newFragSource);
|
||||
ok(false, "Fragment shader was compiled with a defective source!");
|
||||
} catch (error) {
|
||||
ok(error,
|
||||
"The new fragment shader source was compiled with errors.");
|
||||
is(error.compile, "",
|
||||
"The compilation status should be empty.");
|
||||
isnot(error.link, "",
|
||||
"The linkage status should not be empty.");
|
||||
is(error.link.split("ERROR").length - 1, 1,
|
||||
"The linkage status contains one error.");
|
||||
ok(error.link.contains("ERROR: 0:6: 'constructor'"),
|
||||
"A constructor error is contained in the linkage status.");
|
||||
}
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
ok(true, "The shader was reverted to the old source.");
|
||||
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
ok(fragSource.contains("vec3 vFragmentColor;"),
|
||||
"The previous correct fragment shader source was preserved.");
|
||||
|
||||
yield programActor.highlight([0, 0, 1, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
ok(true, "Highlighting worked after setting a defective fragment source.");
|
||||
|
||||
yield programActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
|
||||
ok(true, "Unhighlighting worked after setting a defective vertex source.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the WebGL context is correctly instrumented every time the
|
||||
* target navigates.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield front.setup();
|
||||
yield linked;
|
||||
ok(true, "Canvas was correctly instrumented on the first navigation.");
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield reload(target);
|
||||
yield linked;
|
||||
ok(true, "Canvas was correctly instrumented on the second navigation.");
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield reload(target);
|
||||
yield linked;
|
||||
ok(true, "Canvas was correctly instrumented on the third navigation.");
|
||||
|
||||
let programActor = yield linked;
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color was correct before highlighting.");
|
||||
|
||||
yield programActor.highlight([0, 0, 1, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 255, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after highlighting.");
|
||||
|
||||
yield programActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
|
||||
ok(true, "The top left pixel color is correct after unhighlighting.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the WebGL context is never instrumented anymore after the
|
||||
* finalize method is called.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SIMPLE_CANVAS_URL);
|
||||
|
||||
let linked = once(front, "program-linked");
|
||||
yield front.setup();
|
||||
yield linked;
|
||||
ok(true, "Canvas was correctly instrumented on the first navigation.");
|
||||
|
||||
once(front, "program-linked").then(() => {
|
||||
ok(false, "A 'program-linked' notification shouldn't have been sent!");
|
||||
});
|
||||
|
||||
yield front.finalize();
|
||||
yield reload(target);
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the correct vertex and fragment shader sources are retrieved
|
||||
* regardless of the order in which they were compiled and attached.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(SHADER_ORDER_URL);
|
||||
front.setup();
|
||||
|
||||
let programActor = yield once(front, "program-linked");
|
||||
let vertexShader = yield programActor.getVertexShader();
|
||||
let fragmentShader = yield programActor.getFragmentShader();
|
||||
|
||||
let vertSource = yield vertexShader.getText();
|
||||
let fragSource = yield fragmentShader.getText();
|
||||
|
||||
ok(vertSource.contains("I'm a vertex shader!"),
|
||||
"The correct vertex shader text was retrieved.");
|
||||
ok(fragSource.contains("I'm a fragment shader!"),
|
||||
"The correct fragment shader text was retrieved.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if multiple WebGL contexts are correctly handled.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
|
||||
front.setup();
|
||||
|
||||
let firstProgramActor = yield once(front, "program-linked");
|
||||
let secondProgramActor = yield once(front, "program-linked");
|
||||
|
||||
isnot(firstProgramActor, secondProgramActor,
|
||||
"Two distinct program actors were recevide from two separate contexts.");
|
||||
|
||||
let firstVertexShader = yield firstProgramActor.getVertexShader();
|
||||
let firstFragmentShader = yield firstProgramActor.getFragmentShader();
|
||||
let secondVertexShader = yield secondProgramActor.getVertexShader();
|
||||
let secondFragmentShader = yield secondProgramActor.getFragmentShader();
|
||||
|
||||
isnot(firstVertexShader, secondVertexShader,
|
||||
"The two programs should have distinct vertex shaders.");
|
||||
isnot(firstFragmentShader, secondFragmentShader,
|
||||
"The two programs should have distinct fragment shaders.");
|
||||
|
||||
let firstVertSource = yield firstVertexShader.getText();
|
||||
let firstFragSource = yield firstFragmentShader.getText();
|
||||
let secondVertSource = yield secondVertexShader.getText();
|
||||
let secondFragSource = yield secondFragmentShader.getText();
|
||||
|
||||
is(firstVertSource, secondVertSource,
|
||||
"The vertex shaders should have identical sources.");
|
||||
is(firstFragSource, secondFragSource,
|
||||
"The vertex shaders should have identical sources.");
|
||||
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two canvases are correctly drawn.");
|
||||
|
||||
yield firstProgramActor.highlight([1, 0, 0, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The first canvas was correctly filled after highlighting.");
|
||||
|
||||
yield secondProgramActor.highlight([0, 1, 0, 1]);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 0, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 0, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 0, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The second canvas was correctly filled after highlighting.");
|
||||
|
||||
yield firstProgramActor.unhighlight();
|
||||
yield secondProgramActor.unhighlight();
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The two canvases were correctly filled after unhighlighting.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the rendering is updated when a uniform variable is
|
||||
* changed in one shader of a page with multiple WebGL contexts.
|
||||
*/
|
||||
|
||||
function ifWebGLSupported() {
|
||||
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
|
||||
front.setup();
|
||||
|
||||
let firstProgramActor = yield once(front, "program-linked");
|
||||
let secondProgramActor = yield once(front, "program-linked");
|
||||
let firstFragmentShader = yield firstProgramActor.getFragmentShader();
|
||||
let secondFragmentShader = yield secondProgramActor.getFragmentShader();
|
||||
|
||||
let oldFragSource = yield firstFragmentShader.getText();
|
||||
let newFragSource = oldFragSource.replace("vec4(uColor", "vec4(0.25, 0.25, 0.25");
|
||||
let status = yield firstFragmentShader.compile(newFragSource);
|
||||
ok(!status,
|
||||
"The first new fragment shader source was compiled without errors.");
|
||||
|
||||
yield waitForFrame(debuggee);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 64, g: 64, b: 64, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 64, g: 64, b: 64, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 0, g: 255, b: 255, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The first fragment shader was changed.");
|
||||
|
||||
let oldFragSource = yield secondFragmentShader.getText();
|
||||
let newFragSource = oldFragSource.replace("vec4(uColor", "vec4(0.75, 0.75, 0.75");
|
||||
let status = yield secondFragmentShader.compile(newFragSource);
|
||||
ok(!status,
|
||||
"The second new fragment shader source was compiled without errors.");
|
||||
|
||||
yield waitForFrame(debuggee);
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 64, g: 64, b: 64, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 64, g: 64, b: 64, a: 255 }, true, "#canvas1");
|
||||
yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 191, g: 191, b: 191, a: 255 }, true, "#canvas2");
|
||||
yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 191, g: 191, b: 191, a: 255 }, true, "#canvas2");
|
||||
ok(true, "The second fragment shader was changed.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>WebGL editor test page</title>
|
||||
|
||||
<script id="shader-vs" type="x-shader/x-vertex">
|
||||
precision lowp float;
|
||||
attribute vec3 aVertexPosition;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = vec4(aVertexPosition, 1);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="shader-fs" type="x-shader/x-fragment">
|
||||
precision lowp float;
|
||||
uniform vec3 uColor;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(uColor, 1);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas id="canvas1" width="128" height="128"></canvas>
|
||||
<canvas id="canvas2" width="128" height="128"></canvas>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
"use strict";
|
||||
|
||||
let canvas = [], gl = [];
|
||||
let program = [];
|
||||
let squareVerticesPositionBuffer = [];
|
||||
let vertexPositionAttribute = [];
|
||||
let colorUniform = [];
|
||||
|
||||
window.onload = function() {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
canvas[i] = document.querySelector("#canvas" + (i + 1));
|
||||
gl[i] = canvas[i].getContext("webgl");
|
||||
gl[i].clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
initProgram(i);
|
||||
initBuffers(i);
|
||||
drawScene(i);
|
||||
}
|
||||
}
|
||||
|
||||
function initProgram(i) {
|
||||
let vertexShader = getShader(gl[i], "shader-vs");
|
||||
let fragmentShader = getShader(gl[i], "shader-fs");
|
||||
|
||||
program[i] = gl[i].createProgram();
|
||||
gl[i].attachShader(program[i], vertexShader);
|
||||
gl[i].attachShader(program[i], fragmentShader);
|
||||
gl[i].linkProgram(program[i]);
|
||||
|
||||
vertexPositionAttribute[i] = gl[i].getAttribLocation(program[i], "aVertexPosition");
|
||||
gl[i].enableVertexAttribArray(vertexPositionAttribute[i]);
|
||||
|
||||
colorUniform[i] = gl[i].getUniformLocation(program[i], "uColor");
|
||||
}
|
||||
|
||||
function getShader(gl, id) {
|
||||
let script = document.getElementById(id);
|
||||
let source = script.textContent;
|
||||
let shader;
|
||||
|
||||
if (script.type == "x-shader/x-fragment") {
|
||||
shader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
} else if (script.type == "x-shader/x-vertex") {
|
||||
shader = gl.createShader(gl.VERTEX_SHADER);
|
||||
}
|
||||
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
function initBuffers(i) {
|
||||
squareVerticesPositionBuffer[i] = gl[i].createBuffer();
|
||||
gl[i].bindBuffer(gl[i].ARRAY_BUFFER, squareVerticesPositionBuffer[i]);
|
||||
gl[i].bufferData(gl[i].ARRAY_BUFFER, new Float32Array([
|
||||
1.0, 1.0, 0.0,
|
||||
-1.0, 1.0, 0.0,
|
||||
1.0, -1.0, 0.0,
|
||||
-1.0, -1.0, 0.0
|
||||
]), gl[i].STATIC_DRAW);
|
||||
}
|
||||
|
||||
function drawScene(i) {
|
||||
gl[i].clear(gl[i].COLOR_BUFFER_BIT);
|
||||
|
||||
gl[i].bindBuffer(gl[i].ARRAY_BUFFER, squareVerticesPositionBuffer[i]);
|
||||
gl[i].vertexAttribPointer(vertexPositionAttribute[i], 3, gl[i].FLOAT, false, 0, 0);
|
||||
|
||||
gl[i].useProgram(program[i]);
|
||||
gl[i].uniform3fv(colorUniform[i], i == 0 ? [1, 1, 0] : [0, 1, 1]);
|
||||
gl[i].drawArrays(gl[i].TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
window.requestAnimationFrame(() => drawScene(i));
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,83 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>WebGL editor test page</title>
|
||||
|
||||
<script id="shader-vs" type="x-shader/x-vertex">
|
||||
precision lowp float;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = vec4(0, 0, 0, 1); // I'm a vertex shader!
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="shader-fs" type="x-shader/x-fragment">
|
||||
precision lowp float;
|
||||
varying vec3 vFragmentColor;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(1, 0, 0, 1); // I'm a fragment shader!
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas width="512" height="512"></canvas>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
"use strict";
|
||||
|
||||
let canvas, gl;
|
||||
|
||||
window.onload = function() {
|
||||
canvas = document.querySelector("canvas");
|
||||
gl = canvas.getContext("webgl");
|
||||
|
||||
let shaderProgram = gl.createProgram();
|
||||
let vertexShader, fragmentShader;
|
||||
|
||||
// Compile and attach the shaders in a random order. The test will
|
||||
// ensure that the correct vertex and fragment source is retrieved
|
||||
// regardless of this crazyness.
|
||||
if (Math.random() > 0.5) {
|
||||
vertexShader = getShader(gl, "shader-vs");
|
||||
fragmentShader = getShader(gl, "shader-fs");
|
||||
} else {
|
||||
fragmentShader = getShader(gl, "shader-fs");
|
||||
vertexShader = getShader(gl, "shader-vs");
|
||||
}
|
||||
if (Math.random() > 0.5) {
|
||||
gl.attachShader(shaderProgram, vertexShader);
|
||||
gl.attachShader(shaderProgram, fragmentShader);
|
||||
} else {
|
||||
gl.attachShader(shaderProgram, fragmentShader);
|
||||
gl.attachShader(shaderProgram, vertexShader);
|
||||
}
|
||||
|
||||
gl.linkProgram(shaderProgram);
|
||||
}
|
||||
|
||||
function getShader(gl, id) {
|
||||
let script = document.getElementById(id);
|
||||
let source = script.textContent;
|
||||
let shader;
|
||||
|
||||
if (script.type == "x-shader/x-fragment") {
|
||||
shader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
} else if (script.type == "x-shader/x-vertex") {
|
||||
shader = gl.createShader(gl.VERTEX_SHADER);
|
||||
}
|
||||
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
|
||||
return shader;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,125 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>WebGL editor test page</title>
|
||||
|
||||
<script id="shader-vs" type="x-shader/x-vertex">
|
||||
precision lowp float;
|
||||
attribute vec3 aVertexPosition;
|
||||
attribute vec3 aVertexColor;
|
||||
varying vec3 vFragmentColor;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = vec4(aVertexPosition, 1.0);
|
||||
vFragmentColor = aVertexColor; // I'm special!
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="shader-fs" type="x-shader/x-fragment">
|
||||
precision lowp float;
|
||||
varying vec3 vFragmentColor;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(vFragmentColor, 1.0); // I'm also special!
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<canvas width="512" height="512"></canvas>
|
||||
|
||||
<script type="text/javascript;version=1.8">
|
||||
"use strict";
|
||||
|
||||
let canvas, gl;
|
||||
let program;
|
||||
let squareVerticesPositionBuffer;
|
||||
let squareVerticesColorBuffer;
|
||||
let vertexPositionAttribute;
|
||||
let vertexColorAttribute;
|
||||
|
||||
window.onload = function() {
|
||||
canvas = document.querySelector("canvas");
|
||||
gl = canvas.getContext("webgl");
|
||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||
|
||||
initProgram();
|
||||
initBuffers();
|
||||
drawScene();
|
||||
}
|
||||
|
||||
function initProgram() {
|
||||
let vertexShader = getShader(gl, "shader-vs");
|
||||
let fragmentShader = getShader(gl, "shader-fs");
|
||||
|
||||
program = gl.createProgram();
|
||||
gl.attachShader(program, vertexShader);
|
||||
gl.attachShader(program, fragmentShader);
|
||||
gl.linkProgram(program);
|
||||
|
||||
vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition");
|
||||
gl.enableVertexAttribArray(vertexPositionAttribute);
|
||||
|
||||
vertexColorAttribute = gl.getAttribLocation(program, "aVertexColor");
|
||||
gl.enableVertexAttribArray(vertexColorAttribute);
|
||||
}
|
||||
|
||||
function getShader(gl, id) {
|
||||
let script = document.getElementById(id);
|
||||
let source = script.textContent;
|
||||
let shader;
|
||||
|
||||
if (script.type == "x-shader/x-fragment") {
|
||||
shader = gl.createShader(gl.FRAGMENT_SHADER);
|
||||
} else if (script.type == "x-shader/x-vertex") {
|
||||
shader = gl.createShader(gl.VERTEX_SHADER);
|
||||
}
|
||||
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
function initBuffers() {
|
||||
squareVerticesPositionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesPositionBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
||||
1.0, 1.0, 0.0,
|
||||
-1.0, 1.0, 0.0,
|
||||
1.0, -1.0, 0.0,
|
||||
-1.0, -1.0, 0.0
|
||||
]), gl.STATIC_DRAW);
|
||||
|
||||
squareVerticesColorBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
|
||||
1.0, 1.0, 1.0, 1.0,
|
||||
1.0, 0.0, 0.0, 1.0,
|
||||
0.0, 1.0, 0.0, 1.0,
|
||||
0.0, 0.0, 1.0, 1.0
|
||||
]), gl.STATIC_DRAW);
|
||||
}
|
||||
|
||||
function drawScene() {
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesPositionBuffer);
|
||||
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, squareVerticesColorBuffer);
|
||||
gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
|
||||
|
||||
gl.useProgram(program);
|
||||
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
window.requestAnimationFrame(drawScene);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,252 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
// Enable logging for all the tests. Both the debugger server and frontend will
|
||||
// be affected by this pref.
|
||||
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||
|
||||
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
||||
|
||||
let { WebGLFront } = devtools.require("devtools/server/actors/webgl");
|
||||
let TiltGL = devtools.require("devtools/tilt/tilt-gl");
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
let Toolbox = devtools.Toolbox;
|
||||
|
||||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/shadereditor/test/";
|
||||
const SIMPLE_CANVAS_URL = EXAMPLE_URL + "doc_simple-canvas.html";
|
||||
const SHADER_ORDER_URL = EXAMPLE_URL + "doc_shader-order.html";
|
||||
const MULTIPLE_CONTEXTS_URL = EXAMPLE_URL + "doc_multiple-contexts.html";
|
||||
|
||||
// All tests are asynchronous.
|
||||
waitForExplicitFinish();
|
||||
|
||||
let gToolEnabled = Services.prefs.getBoolPref("devtools.shadereditor.enabled");
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
info("finish() was called, cleaning up...");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
|
||||
Services.prefs.setBoolPref("devtools.shadereditor.enabled", gToolEnabled);
|
||||
});
|
||||
|
||||
function addTab(aUrl, aWindow) {
|
||||
info("Adding tab: " + aUrl);
|
||||
|
||||
let deferred = promise.defer();
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
targetWindow.focus();
|
||||
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
linkedBrowser.addEventListener("load", function onLoad() {
|
||||
linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
info("Tab added and finished loading: " + aUrl);
|
||||
deferred.resolve(tab);
|
||||
}, true);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function removeTab(aTab, aWindow) {
|
||||
info("Removing tab.");
|
||||
|
||||
let deferred = promise.defer();
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
let tabContainer = targetBrowser.tabContainer;
|
||||
|
||||
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
|
||||
tabContainer.removeEventListener("TabClose", onClose, false);
|
||||
info("Tab removed and finished closing.");
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
|
||||
targetBrowser.removeTab(aTab);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function handleError(aError) {
|
||||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
finish();
|
||||
}
|
||||
|
||||
function ifWebGLSupported() {
|
||||
ok(false, "You need to define a 'ifWebGLSupported' function.");
|
||||
finish();
|
||||
}
|
||||
|
||||
function ifWebGLUnsupported() {
|
||||
todo(false, "Skipping test because WebGL isn't supported.");
|
||||
finish();
|
||||
}
|
||||
|
||||
function test() {
|
||||
let generator = isWebGLSupported() ? ifWebGLSupported : ifWebGLUnsupported;
|
||||
Task.spawn(generator).then(null, handleError);
|
||||
}
|
||||
|
||||
function createCanvas() {
|
||||
return document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
}
|
||||
|
||||
function isWebGLSupported() {
|
||||
let supported =
|
||||
!TiltGL.isWebGLForceEnabled() &&
|
||||
TiltGL.isWebGLSupported() &&
|
||||
TiltGL.create3DContext(createCanvas());
|
||||
|
||||
info("Apparently, WebGL is" + (supported ? "" : " not") + " supported.");
|
||||
return supported;
|
||||
}
|
||||
|
||||
function once(aTarget, aEventName, aUseCapture = false) {
|
||||
info("Waiting for event: '" + aEventName + "' on " + aTarget + ".");
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
||||
for (let [add, remove] of [
|
||||
["addEventListener", "removeEventListener"],
|
||||
["addListener", "removeListener"],
|
||||
["on", "off"]
|
||||
]) {
|
||||
if ((add in aTarget) && (remove in aTarget)) {
|
||||
aTarget[add](aEventName, function onEvent(...aArgs) {
|
||||
aTarget[remove](aEventName, onEvent, aUseCapture);
|
||||
deferred.resolve.apply(deferred, aArgs);
|
||||
}, aUseCapture);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function waitForFrame(aDebuggee) {
|
||||
let deferred = promise.defer();
|
||||
aDebuggee.mozRequestAnimationFrame(deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function isApprox(aFirst, aSecond, aMargin = 1) {
|
||||
return Math.abs(aFirst - aSecond) <= aMargin;
|
||||
}
|
||||
|
||||
function isApproxColor(aFirst, aSecond, aMargin) {
|
||||
return isApprox(aFirst.r, aSecond.r, aMargin) &&
|
||||
isApprox(aFirst.g, aSecond.g, aMargin) &&
|
||||
isApprox(aFirst.b, aSecond.b, aMargin) &&
|
||||
isApprox(aFirst.a, aSecond.a, aMargin);
|
||||
}
|
||||
|
||||
function getPixels(aDebuggee, aSelector = "canvas") {
|
||||
let canvas = aDebuggee.document.querySelector(aSelector);
|
||||
let gl = canvas.getContext("webgl");
|
||||
|
||||
let { width, height } = canvas;
|
||||
let buffer = new aDebuggee.Uint8Array(width * height * 4);
|
||||
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
|
||||
|
||||
info("Retrieved pixels: " + width + "x" + height);
|
||||
return [buffer, width, height];
|
||||
}
|
||||
|
||||
function getPixel(aDebuggee, aPosition, aSelector = "canvas") {
|
||||
let canvas = aDebuggee.document.querySelector(aSelector);
|
||||
let gl = canvas.getContext("webgl");
|
||||
|
||||
let { width, height } = canvas;
|
||||
let { x, y } = aPosition;
|
||||
let buffer = new aDebuggee.Uint8Array(4);
|
||||
gl.readPixels(x, height - y - 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buffer);
|
||||
|
||||
let pixel = { r: buffer[0], g: buffer[1], b: buffer[2], a: buffer[3] };
|
||||
|
||||
info("Retrieved pixel: " + pixel.toSource() + " at " + aPosition.toSource());
|
||||
return pixel;
|
||||
}
|
||||
|
||||
function ensurePixelIs(aDebuggee, aPosition, aColor, aWaitFlag = false, aSelector = "canvas") {
|
||||
let pixel = getPixel(aDebuggee, aPosition, aSelector);
|
||||
if (isApproxColor(pixel, aColor)) {
|
||||
ok(true, "Expected pixel is shown at: " + aPosition.toSource());
|
||||
return promise.resolve(null);
|
||||
}
|
||||
if (aWaitFlag) {
|
||||
return Task.spawn(function() {
|
||||
yield waitForFrame(aDebuggee);
|
||||
yield ensurePixelIs(aDebuggee, aPosition, aColor, aWaitFlag, aSelector);
|
||||
});
|
||||
}
|
||||
ok(false, "Expected pixel was not already shown at: " + aPosition.toSource());
|
||||
return promise.reject(null);
|
||||
}
|
||||
|
||||
function navigate(aTarget, aUrl) {
|
||||
let navigated = once(aTarget, "navigate");
|
||||
aTarget.client.activeTab.navigateTo(aUrl);
|
||||
return navigated;
|
||||
}
|
||||
|
||||
function reload(aTarget) {
|
||||
let navigated = once(aTarget, "navigate");
|
||||
aTarget.client.activeTab.reload();
|
||||
return navigated;
|
||||
}
|
||||
|
||||
function initBackend(aUrl) {
|
||||
info("Initializing a shader editor front.");
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init(() => true);
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
return Task.spawn(function*() {
|
||||
let tab = yield addTab(aUrl);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
let debuggee = target.window.wrappedJSObject;
|
||||
|
||||
yield target.makeRemote();
|
||||
|
||||
let front = new WebGLFront(target.client, target.form);
|
||||
return [target, debuggee, front];
|
||||
});
|
||||
}
|
||||
|
||||
function initShaderEditor(aUrl) {
|
||||
info("Initializing a shader editor pane.");
|
||||
|
||||
return Task.spawn(function*() {
|
||||
let tab = yield addTab(aUrl);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
let debuggee = target.window.wrappedJSObject;
|
||||
|
||||
yield target.makeRemote();
|
||||
|
||||
Services.prefs.setBoolPref("devtools.shadereditor.enabled", true);
|
||||
let toolbox = yield gDevTools.showToolbox(target, "shadereditor");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
return [target, debuggee, panel];
|
||||
});
|
||||
}
|
||||
|
||||
function teardown(aPanel) {
|
||||
info("Destroying the specified shader editor.");
|
||||
|
||||
return promise.all([
|
||||
once(aPanel, "destroyed"),
|
||||
removeTab(aPanel.target.tab)
|
||||
]);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['browser.ini']
|
|
@ -118,6 +118,11 @@ Telemetry.prototype = {
|
|||
userHistogram: "DEVTOOLS_STYLEEDITOR_OPENED_PER_USER_FLAG",
|
||||
timerHistogram: "DEVTOOLS_STYLEEDITOR_TIME_ACTIVE_SECONDS"
|
||||
},
|
||||
shadereditor: {
|
||||
histogram: "DEVTOOLS_SHADEREDITOR_OPENED_BOOLEAN",
|
||||
userHistogram: "DEVTOOLS_SHADEREDITOR_OPENED_PER_USER_FLAG",
|
||||
timerHistogram: "DEVTOOLS_SHADEREDITOR_TIME_ACTIVE_SECONDS"
|
||||
},
|
||||
jsprofiler: {
|
||||
histogram: "DEVTOOLS_JSPROFILER_OPENED_BOOLEAN",
|
||||
userHistogram: "DEVTOOLS_JSPROFILER_OPENED_PER_USER_FLAG",
|
||||
|
|
|
@ -166,7 +166,8 @@ SideMenuWidget.prototype = {
|
|||
* The element associated with the displayed item.
|
||||
*/
|
||||
removeChild: function(aChild) {
|
||||
if (aChild.classList.contains("side-menu-widget-item-contents")) {
|
||||
if (aChild.classList.contains("side-menu-widget-item-contents") &&
|
||||
!aChild.classList.contains("side-menu-widget-item")) {
|
||||
// Remove the item itself, not the contents.
|
||||
aChild.parentNode.remove();
|
||||
} else {
|
||||
|
|
|
@ -892,6 +892,40 @@ VariablesView.prototype = {
|
|||
this._emptyTextNode = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets if all values should be aligned together.
|
||||
* @return boolean
|
||||
*/
|
||||
get alignedValues() {
|
||||
return this._alignedValues;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets if all values should be aligned together.
|
||||
* @param boolean aFlag
|
||||
*/
|
||||
set alignedValues(aFlag) {
|
||||
this._alignedValues = aFlag;
|
||||
if (aFlag) {
|
||||
this._parent.setAttribute("aligned-values", "");
|
||||
} else {
|
||||
this._parent.removeAttribute("aligned-values");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets if action buttons (like delete) should be placed at the beginning or
|
||||
* end of a line.
|
||||
* @param boolean aFlag
|
||||
*/
|
||||
set actionsFirst(aFlag) {
|
||||
if (aFlag) {
|
||||
this._parent.setAttribute("actions-first", "");
|
||||
} else {
|
||||
this._parent.removeAttribute("actions-first");
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the parent node holding this view.
|
||||
* @return nsIDOMNode
|
||||
|
@ -1726,6 +1760,7 @@ Scope.prototype = {
|
|||
}
|
||||
let throbber = this._throbber = this.document.createElement("hbox");
|
||||
throbber.className = "variables-view-throbber";
|
||||
throbber.setAttribute("optional-visibility", "");
|
||||
this._title.insertBefore(throbber, this._spacer);
|
||||
},
|
||||
|
||||
|
@ -2322,6 +2357,7 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
|
|||
valueLabel.setAttribute("crop", "center");
|
||||
|
||||
let spacer = this._spacer = document.createElement("spacer");
|
||||
spacer.setAttribute("optional-visibility", "");
|
||||
spacer.setAttribute("flex", "1");
|
||||
|
||||
this._title.appendChild(separatorLabel);
|
||||
|
@ -2333,7 +2369,7 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
|
|||
}
|
||||
|
||||
// If no value will be displayed, we don't need the separator.
|
||||
if (!descriptor.get && !descriptor.set && !descriptor.value) {
|
||||
if (!descriptor.get && !descriptor.set && !("value" in descriptor)) {
|
||||
separatorLabel.hidden = true;
|
||||
}
|
||||
|
||||
|
@ -2384,7 +2420,6 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
|
|||
if (ownerView.delete) {
|
||||
let deleteNode = this._deleteNode = this.document.createElement("toolbarbutton");
|
||||
deleteNode.className = "plain variables-view-delete";
|
||||
deleteNode.setAttribute("ordinal", 2);
|
||||
deleteNode.addEventListener("click", this._onDelete.bind(this), false);
|
||||
this._title.appendChild(deleteNode);
|
||||
}
|
||||
|
@ -2399,24 +2434,28 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
|
|||
if (!descriptor.writable && !ownerView.getter && !ownerView.setter) {
|
||||
let nonWritableIcon = this.document.createElement("hbox");
|
||||
nonWritableIcon.className = "variable-or-property-non-writable-icon";
|
||||
nonWritableIcon.setAttribute("optional-visibility", "");
|
||||
this._title.appendChild(nonWritableIcon);
|
||||
}
|
||||
if (descriptor.value && typeof descriptor.value == "object") {
|
||||
if (descriptor.value.frozen) {
|
||||
let frozenLabel = this.document.createElement("label");
|
||||
frozenLabel.className = "plain variable-or-property-frozen-label";
|
||||
frozenLabel.setAttribute("optional-visibility", "");
|
||||
frozenLabel.setAttribute("value", "F");
|
||||
this._title.appendChild(frozenLabel);
|
||||
}
|
||||
if (descriptor.value.sealed) {
|
||||
let sealedLabel = this.document.createElement("label");
|
||||
sealedLabel.className = "plain variable-or-property-sealed-label";
|
||||
sealedLabel.setAttribute("optional-visibility", "");
|
||||
sealedLabel.setAttribute("value", "S");
|
||||
this._title.appendChild(sealedLabel);
|
||||
}
|
||||
if (!descriptor.value.extensible) {
|
||||
let nonExtensibleLabel = this.document.createElement("label");
|
||||
nonExtensibleLabel.className = "plain variable-or-property-non-extensible-label";
|
||||
nonExtensibleLabel.setAttribute("optional-visibility", "");
|
||||
nonExtensibleLabel.setAttribute("value", "N");
|
||||
this._title.appendChild(nonExtensibleLabel);
|
||||
}
|
||||
|
@ -2557,7 +2596,9 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
|
|||
let input = this.document.createElement("textbox");
|
||||
input.className = "plain " + aClassName;
|
||||
input.setAttribute("value", initialString);
|
||||
input.setAttribute("flex", "1");
|
||||
if (!this._variablesView.alignedValues) {
|
||||
input.setAttribute("flex", "1");
|
||||
}
|
||||
|
||||
// Replace the specified label with a textbox input element.
|
||||
aLabel.parentNode.replaceChild(input, aLabel);
|
||||
|
|
|
@ -973,6 +973,18 @@ this.WidgetMethods = {
|
|||
return "";
|
||||
},
|
||||
|
||||
/**
|
||||
* Retrieves the attachment of the selected element.
|
||||
* @return string
|
||||
*/
|
||||
get selectedAttachment() {
|
||||
let selectedElement = this._widget.selectedItem;
|
||||
if (selectedElement) {
|
||||
return this._itemsByElement.get(selectedElement).attachment;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects the element with the entangled item in this container.
|
||||
* @param Item | function aItem
|
||||
|
|
|
@ -57,3 +57,11 @@
|
|||
.variable-or-property:not([sealed]) > tooltip > label[value=sealed] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
*:not(:hover) .variables-view-delete {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.variables-view-container[aligned-values] .title > [optional-visibility] {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -226,6 +226,7 @@ Editor.prototype = {
|
|||
this.showContextMenu(doc, ev.screenX, ev.screenY);
|
||||
}, false);
|
||||
|
||||
cm.on("focus", () => this.emit("focus"));
|
||||
cm.on("change", () => this.emit("change"));
|
||||
cm.on("gutterClick", (cm, line) => this.emit("gutterClick", line));
|
||||
cm.on("cursorActivity", (cm) => this.emit("cursorActivity"));
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<!-- 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/. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE : FILE This file contains the Debugger strings -->
|
||||
<!-- LOCALIZATION NOTE : FILE Do not translate commandkey -->
|
||||
|
||||
<!-- LOCALIZATION NOTE : FILE The correct localization of this file might be to
|
||||
- keep it in English, or another language commonly spoken among web developers.
|
||||
- You want to make that choice consistent across the developer tools.
|
||||
- A good criteria is the language in which you'd find the best
|
||||
- documentation on web development on the web. -->
|
||||
|
||||
<!-- LOCALIZATION NOTE (shaderEditorUI.vertexShader): This is the label for
|
||||
- the pane that displays a vertex shader's source. -->
|
||||
<!ENTITY shaderEditorUI.vertexShader "Vertex Shader">
|
||||
|
||||
<!-- LOCALIZATION NOTE (shaderEditorUI.fragmentShader): This is the label for
|
||||
- the pane that displays a fragment shader's source. -->
|
||||
<!ENTITY shaderEditorUI.fragmentShader "Fragment Shader">
|
||||
|
||||
<!-- LOCALIZATION NOTE (shaderEditorUI.reloadNotice1): This is the label shown
|
||||
- on the button that triggers a page refresh. -->
|
||||
<!ENTITY shaderEditorUI.reloadNotice1 "Reload">
|
||||
|
||||
<!-- LOCALIZATION NOTE (shaderEditorUI.reloadNotice2): This is the label shown
|
||||
- along with the button that triggers a page refresh. -->
|
||||
<!ENTITY shaderEditorUI.reloadNotice2 "the page to be able to edit GLSL code.">
|
||||
|
||||
<!-- LOCALIZATION NOTE (shaderEditorUI.emptyNotice): This is the label shown
|
||||
- while the page is refreshing and the tool waits for a WebGL context. -->
|
||||
<!ENTITY shaderEditorUI.emptyNotice "Waiting for a WebGL context to be created…">
|
|
@ -0,0 +1,32 @@
|
|||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE These strings are used inside the Debugger
|
||||
# which is available from the Web Developer sub-menu -> 'Debugger'.
|
||||
# The correct localization of this file might be to keep it in
|
||||
# English, or another language commonly spoken among web developers.
|
||||
# You want to make that choice consistent across the developer tools.
|
||||
# A good criteria is the language in which you'd find the best
|
||||
# documentation on web development on the web.
|
||||
|
||||
# LOCALIZATION NOTE (ToolboxShaderEditor.label):
|
||||
# This string is displayed in the title of the tab when the Shader Editor is
|
||||
# displayed inside the developer tools window and in the Developer Tools Menu.
|
||||
ToolboxShaderEditor.label=Shader Editor
|
||||
|
||||
# LOCALIZATION NOTE (ToolboxShaderEditor.tooltip):
|
||||
# This string is displayed in the tooltip of the tab when the Shader Editor is
|
||||
# displayed inside the developer tools window.
|
||||
ToolboxShaderEditor.tooltip=Live GLSL shader language editor for WebGL
|
||||
|
||||
# LOCALIZATION NOTE (shadersList.programLabel):
|
||||
# This string is displayed in the programs list of the Shader Editor,
|
||||
# identifying a set of linked GLSL shaders.
|
||||
shadersList.programLabel=Program %S
|
||||
|
||||
# LOCALIZATION NOTE (shadersList.blackboxLabel):
|
||||
# This string is displayed in the programs list of the Shader Editor, while
|
||||
# the user hovers over the checkbox used to toggle blackboxing of a program's
|
||||
# associated fragment shader.
|
||||
shadersList.blackboxLabel=Toggle geometry visibility
|
|
@ -27,6 +27,8 @@
|
|||
locale/browser/devtools/debugger.properties (%chrome/browser/devtools/debugger.properties)
|
||||
locale/browser/devtools/netmonitor.dtd (%chrome/browser/devtools/netmonitor.dtd)
|
||||
locale/browser/devtools/netmonitor.properties (%chrome/browser/devtools/netmonitor.properties)
|
||||
locale/browser/devtools/shadereditor.dtd (%chrome/browser/devtools/shadereditor.dtd)
|
||||
locale/browser/devtools/shadereditor.properties (%chrome/browser/devtools/shadereditor.properties)
|
||||
locale/browser/devtools/gcli.properties (%chrome/browser/devtools/gcli.properties)
|
||||
locale/browser/devtools/gclicommands.properties (%chrome/browser/devtools/gclicommands.properties)
|
||||
locale/browser/devtools/webconsole.properties (%chrome/browser/devtools/webconsole.properties)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
/* 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/. */
|
||||
|
||||
%include ../../shared/devtools/shadereditor.inc.css
|
|
@ -565,6 +565,26 @@
|
|||
text-shadow: 0 0 8px #ccf;
|
||||
}
|
||||
|
||||
/* Aligned values */
|
||||
|
||||
.variables-view-container[aligned-values] .title > .separator {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
.variables-view-container[aligned-values] .title > .value {
|
||||
width: 70vw;
|
||||
}
|
||||
|
||||
.variables-view-container[aligned-values] .title > .element-value-input {
|
||||
width: calc(70vw - 10px);
|
||||
}
|
||||
|
||||
/* Actions first */
|
||||
|
||||
.variables-view-container[actions-first] .variables-view-delete {
|
||||
-moz-box-ordinal-group: 0;
|
||||
}
|
||||
|
||||
/* Variables and properties tooltips */
|
||||
|
||||
.variable-or-property > tooltip > label {
|
||||
|
@ -600,10 +620,6 @@
|
|||
-moz-image-region: rect(0,48px,16px,32px);
|
||||
}
|
||||
|
||||
*:not(:hover) .variables-view-delete {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.variables-view-delete > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
@ -667,3 +683,5 @@
|
|||
.arrow[invisible] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
%include ../../shared/devtools/app-manager/manifest-editor.inc.css
|
||||
|
|
|
@ -127,7 +127,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css)
|
||||
skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css)
|
||||
skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png)
|
||||
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png)
|
||||
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
|
||||
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
||||
|
@ -172,6 +172,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/breadcrumbs/rtl-start-selected.png (devtools/breadcrumbs/rtl-start-selected.png)
|
||||
skin/classic/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
/* 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/. */
|
||||
|
||||
%include ../shared.inc
|
||||
%include ../../shared/devtools/shadereditor.inc.css
|
|
@ -565,6 +565,26 @@
|
|||
text-shadow: 0 0 8px #ccf;
|
||||
}
|
||||
|
||||
/* Aligned values */
|
||||
|
||||
.variables-view-container[aligned-values] .title > .separator {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
.variables-view-container[aligned-values] .title > .value {
|
||||
width: 70vw;
|
||||
}
|
||||
|
||||
.variables-view-container[aligned-values] .title > .element-value-input {
|
||||
width: calc(70vw - 10px);
|
||||
}
|
||||
|
||||
/* Actions first */
|
||||
|
||||
.variables-view-container[actions-first] .variables-view-delete {
|
||||
-moz-box-ordinal-group: 0;
|
||||
}
|
||||
|
||||
/* Variables and properties tooltips */
|
||||
|
||||
.variable-or-property > tooltip > label {
|
||||
|
@ -600,10 +620,6 @@
|
|||
-moz-image-region: rect(0,48px,16px,32px);
|
||||
}
|
||||
|
||||
*:not(:hover) .variables-view-delete {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.variables-view-delete > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
@ -663,3 +679,5 @@
|
|||
.arrow[invisible] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
%include ../../shared/devtools/app-manager/manifest-editor.inc.css
|
||||
|
|
|
@ -219,7 +219,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css)
|
||||
skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css)
|
||||
skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png)
|
||||
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png)
|
||||
skin/classic/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
|
||||
skin/classic/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
||||
|
@ -264,6 +264,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/breadcrumbs/rtl-start-selected.png (devtools/breadcrumbs/rtl-start-selected.png)
|
||||
skin/classic/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
|
|
|
@ -6,5 +6,5 @@
|
|||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="64px" height="64px" viewBox="0 0 64 64">
|
||||
<path d="m 12.183457,12.241457 c -11.129861,11.12986 -11.129861,29.175226 0,40.305086 11.12986,11.129861 29.175226,11.129861 40.305086,0 11.129861,-11.12986 11.129861,-29.175226 0,-40.305086 -11.12986,-11.129861 -29.175226,-11.129861 -40.305086,0 z m 32.241241,14.52963 -5.531697,5.531696 5.388154,5.388154 c 1.82575,1.82575 1.82575,4.823882 0,6.649632 -1.827164,1.827164 -4.825297,1.827164 -6.651047,0.0014 l -5.388153,-5.388153 -5.527454,5.527453 c -1.781909,1.781909 -4.686704,1.779081 -6.465784,0 -1.779081,-1.77908 -1.781202,-4.684582 0,-6.465784 l 5.527453,-5.527454 -5.388153,-5.388153 c -1.82575,-1.82575 -1.82575,-4.823883 0.0014,-6.651047 1.82575,-1.82575 4.823882,-1.82575 6.649632,0 l 5.388154,5.388154 5.531696,-5.531697 c 1.777667,-1.777666 4.68529,-1.777666 6.46437,0.0014 1.779081,1.77908 1.779081,4.686703 0.0014,6.46437 z"
|
||||
style="fill:#d8abab" />
|
||||
style="fill:#FF6B00" />
|
||||
</svg>
|
||||
|
|
До Ширина: | Высота: | Размер: 1.2 KiB После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -0,0 +1,67 @@
|
|||
/* 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/. */
|
||||
|
||||
/* Manifest Editor overrides */
|
||||
|
||||
.variables-view-container.manifest-editor {
|
||||
background-color: #F5F5F5;
|
||||
padding: 20px 13px;
|
||||
}
|
||||
|
||||
.manifest-editor .variable-or-property:focus > .title {
|
||||
background-color: #EDEDED;
|
||||
color: #000;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.manifest-editor .variables-view-property > .title > .name {
|
||||
color: #27406A;
|
||||
}
|
||||
|
||||
.manifest-editor .variable-or-property > .title > label {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.manifest-editor .variable-or-property > .title > .token-string {
|
||||
color: #54BC6A;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.manifest-editor .variable-or-property > .title > .token-boolean,
|
||||
.manifest-editor .variable-or-property > .title > .token-number {
|
||||
color: #009BD4;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.manifest-editor .variable-or-property > .title > .token-undefined {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.manifest-editor .variable-or-property > .title > .token-null {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.manifest-editor .variable-or-property > .title > .token-other {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.manifest-editor .variables-view-variable {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.manifest-editor .variables-view-delete,
|
||||
.manifest-editor .variables-view-delete:hover,
|
||||
.manifest-editor .variables-view-delete:active {
|
||||
list-style-image: none;
|
||||
-moz-image-region: initial;
|
||||
}
|
||||
|
||||
.manifest-editor .variables-view-delete::before {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
background-image: url("app-manager/remove.svg");
|
||||
background-size: 12px auto;
|
||||
}
|
|
@ -110,6 +110,7 @@ strong {
|
|||
right: 5px;
|
||||
bottom: 5px;
|
||||
visibility: hidden;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.project-item:hover .button-remove {
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/* 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/. */
|
||||
|
||||
#body {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
}
|
||||
|
||||
#content {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/* Reload and waiting notices */
|
||||
|
||||
.notice-container {
|
||||
background: transparent;
|
||||
margin-top: -50vh;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#reload-notice {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
#waiting-notice {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
#waiting-notice::before {
|
||||
display: inline-block;
|
||||
content: "";
|
||||
background: url("chrome://global/skin/icons/loading_16.png") center no-repeat;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
-moz-margin-end: 6px;
|
||||
}
|
||||
|
||||
#requests-menu-reload-notice-button {
|
||||
min-height: 2em;
|
||||
}
|
||||
|
||||
/* Shaders pane */
|
||||
|
||||
#shaders-pane {
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
#shaders-pane + .devtools-side-splitter {
|
||||
-moz-border-start-color: transparent;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
-moz-margin-end: -6px;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
|
||||
/* Only show the checkbox when the source is hovered over, is selected, or if it
|
||||
* is not checked. */
|
||||
.side-menu-widget-item:hover > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item.selected > .side-menu-widget-item-checkbox,
|
||||
.side-menu-widget-item-checkbox:not([checked]) {
|
||||
opacity: 1;
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox > .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
background: none;
|
||||
background-image: url("chrome://browser/skin/devtools/itemToggle.png");
|
||||
background-repeat: no-repeat;
|
||||
background-clip: content-box;
|
||||
background-size: 32px 16px;
|
||||
background-position: -16px 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox[checked] > .checkbox-check {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox:not([checked]) ~ .side-menu-widget-item-contents {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
/* Shader source editors */
|
||||
|
||||
#editors-splitter {
|
||||
-moz-border-start-color: rgb(61,69,76);
|
||||
}
|
||||
|
||||
.editor-label {
|
||||
background: url(background-noise-toolbar.png), hsl(208,11%,27%);
|
||||
border-top: 1px solid #222426;
|
||||
padding: 1px 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.editor-label[selected] {
|
||||
background: linear-gradient(hsl(206,61%,40%), hsl(206,61%,31%)) repeat-x top left;
|
||||
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
|
||||
inset 0 -1px 0 hsla(210,40%,83%,.05);
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
/* 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/. */
|
||||
|
||||
%include ../../shared/devtools/shadereditor.inc.css
|
|
@ -568,6 +568,26 @@
|
|||
text-shadow: 0 0 8px #ccf;
|
||||
}
|
||||
|
||||
/* Aligned values */
|
||||
|
||||
.variables-view-container[aligned-values] .title > .separator {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
.variables-view-container[aligned-values] .title > .value {
|
||||
width: 70vw;
|
||||
}
|
||||
|
||||
.variables-view-container[aligned-values] .title > .element-value-input {
|
||||
width: calc(70vw - 10px);
|
||||
}
|
||||
|
||||
/* Actions first */
|
||||
|
||||
.variables-view-container[actions-first] .variables-view-delete {
|
||||
-moz-box-ordinal-group: 0;
|
||||
}
|
||||
|
||||
/* Variables and properties tooltips */
|
||||
|
||||
.variable-or-property > tooltip > label {
|
||||
|
@ -603,10 +623,6 @@
|
|||
-moz-image-region: rect(0,48px,16px,32px);
|
||||
}
|
||||
|
||||
*:not(:hover) .variables-view-delete {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.variables-view-delete > .toolbarbutton-text {
|
||||
display: none;
|
||||
}
|
||||
|
@ -670,3 +686,5 @@
|
|||
.arrow[invisible] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
%include ../../shared/devtools/app-manager/manifest-editor.inc.css
|
||||
|
|
|
@ -154,7 +154,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css)
|
||||
skin/classic/browser/devtools/light-theme.css (../shared/devtools/light-theme.css)
|
||||
skin/classic/browser/devtools/controls.png (../shared/devtools/controls.png)
|
||||
skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
* skin/classic/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
skin/classic/browser/devtools/commandline-icon.png (devtools/commandline-icon.png)
|
||||
skin/classic/browser/devtools/alerticon-warning.png (devtools/alerticon-warning.png)
|
||||
skin/classic/browser/devtools/ruleview.css (devtools/ruleview.css)
|
||||
|
@ -199,6 +199,7 @@ browser.jar:
|
|||
skin/classic/browser/devtools/breadcrumbs/rtl-start-selected.png (devtools/breadcrumbs/rtl-start-selected.png)
|
||||
skin/classic/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
|
@ -430,7 +431,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/dark-theme.css (../shared/devtools/dark-theme.css)
|
||||
skin/classic/aero/browser/devtools/light-theme.css (../shared/devtools/light-theme.css)
|
||||
skin/classic/aero/browser/devtools/controls.png (../shared/devtools/controls.png)
|
||||
skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
* skin/classic/aero/browser/devtools/widgets.css (devtools/widgets.css)
|
||||
skin/classic/aero/browser/devtools/commandline-icon.png (devtools/commandline-icon.png)
|
||||
skin/classic/aero/browser/devtools/command-paintflashing.png (devtools/command-paintflashing.png)
|
||||
skin/classic/aero/browser/devtools/command-responsivemode.png (devtools/command-responsivemode.png)
|
||||
|
@ -475,6 +476,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/devtools/breadcrumbs/rtl-start-selected.png (devtools/breadcrumbs/rtl-start-selected.png)
|
||||
skin/classic/aero/browser/devtools/splitview.css (devtools/splitview.css)
|
||||
skin/classic/aero/browser/devtools/styleeditor.css (devtools/styleeditor.css)
|
||||
* skin/classic/aero/browser/devtools/shadereditor.css (devtools/shadereditor.css)
|
||||
skin/classic/aero/browser/devtools/debugger.css (devtools/debugger.css)
|
||||
* skin/classic/aero/browser/devtools/profiler.css (devtools/profiler.css)
|
||||
skin/classic/aero/browser/devtools/netmonitor.css (devtools/netmonitor.css)
|
||||
|
|
|
@ -71,10 +71,12 @@ public class Tabs implements GeckoEventListener {
|
|||
private final Runnable mPersistTabsRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
boolean syncIsSetup = SyncAccounts.syncAccountsExist(getAppContext());
|
||||
if (syncIsSetup) {
|
||||
TabsAccessor.persistLocalTabs(getContentResolver(), getTabsInOrder());
|
||||
}
|
||||
try {
|
||||
boolean syncIsSetup = SyncAccounts.syncAccountsExist(getAppContext());
|
||||
if (syncIsSetup) {
|
||||
TabsAccessor.persistLocalTabs(getContentResolver(), getTabsInOrder());
|
||||
}
|
||||
} catch (SecurityException se) {} // will fail without android.permission.GET_ACCOUNTS
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -3931,6 +3931,10 @@
|
|||
"kind": "boolean",
|
||||
"description": "How many times has the devtool's Style Editor been opened?"
|
||||
},
|
||||
"DEVTOOLS_SHADEREDITOR_OPENED_BOOLEAN": {
|
||||
"kind": "boolean",
|
||||
"description": "How many times has the devtool's Shader Editor been opened?"
|
||||
},
|
||||
"DEVTOOLS_JSPROFILER_OPENED_BOOLEAN": {
|
||||
"kind": "boolean",
|
||||
"description": "How many times has the devtool's JS Profiler been opened?"
|
||||
|
@ -4003,6 +4007,10 @@
|
|||
"kind": "flag",
|
||||
"description": "How many users have opened the devtool's Style Editor?"
|
||||
},
|
||||
"DEVTOOLS_SHADEREDITOR_OPENED_PER_USER_FLAG": {
|
||||
"kind": "flag",
|
||||
"description": "How many users have opened the devtool's Shader Editor?"
|
||||
},
|
||||
"DEVTOOLS_JSPROFILER_OPENED_PER_USER_FLAG": {
|
||||
"kind": "flag",
|
||||
"description": "How many users have opened the devtool's JS Profiler?"
|
||||
|
@ -4103,6 +4111,12 @@
|
|||
"n_buckets": 100,
|
||||
"description": "How long has the style editor been active (seconds)"
|
||||
},
|
||||
"DEVTOOLS_SHADEREDITOR_TIME_ACTIVE_SECONDS": {
|
||||
"kind": "exponential",
|
||||
"high": "10000000",
|
||||
"n_buckets": 100,
|
||||
"description": "How long has the Shader Editor been active (seconds)"
|
||||
},
|
||||
"DEVTOOLS_JSPROFILER_TIME_ACTIVE_SECONDS": {
|
||||
"kind": "exponential",
|
||||
"high": "10000000",
|
||||
|
|
|
@ -2,13 +2,6 @@
|
|||
* 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/. */
|
||||
|
||||
/**
|
||||
* WARNING: BackgroundPageThumbs.jsm is currently excluded from release builds.
|
||||
* If you use it, you must also exclude your caller when RELEASE_BUILD is
|
||||
* defined, as described here:
|
||||
* https://wiki.mozilla.org/Platform/Channel-specific_build_defines
|
||||
*/
|
||||
|
||||
const EXPORTED_SYMBOLS = [
|
||||
"BackgroundPageThumbs",
|
||||
];
|
||||
|
@ -40,11 +33,6 @@ const BackgroundPageThumbs = {
|
|||
*
|
||||
* The page is loaded anonymously, and plug-ins are disabled.
|
||||
*
|
||||
* WARNING: BackgroundPageThumbs.jsm is currently excluded from release
|
||||
* builds. If you use it, you must also exclude your caller when
|
||||
* RELEASE_BUILD is defined, as described here:
|
||||
* https://wiki.mozilla.org/Platform/Channel-specific_build_defines
|
||||
*
|
||||
* @param url The URL to capture.
|
||||
* @param options An optional object that configures the capture. Its
|
||||
* properties are the following, and all are optional:
|
||||
|
@ -86,11 +74,6 @@ const BackgroundPageThumbs = {
|
|||
* Asynchronously captures a thumbnail of the given URL if one does not
|
||||
* already exist. Otherwise does nothing.
|
||||
*
|
||||
* WARNING: BackgroundPageThumbs.jsm is currently excluded from release
|
||||
* builds. If you use it, you must also exclude your caller when
|
||||
* RELEASE_BUILD is defined, as described here:
|
||||
* https://wiki.mozilla.org/Platform/Channel-specific_build_defines
|
||||
*
|
||||
* @param url The URL to capture.
|
||||
* @param options An optional object that configures the capture. See
|
||||
* capture() for description.
|
||||
|
|
|
@ -3,6 +3,4 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
toolkit.jar:
|
||||
#ifndef RELEASE_BUILD
|
||||
+ content/global/backgroundPageThumbsContent.js (content/backgroundPageThumbsContent.js)
|
||||
#endif
|
||||
|
|
|
@ -12,9 +12,7 @@ EXTRA_COMPONENTS += [
|
|||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'BackgroundPageThumbs.jsm',
|
||||
'PageThumbs.jsm',
|
||||
'PageThumbsWorker.js',
|
||||
]
|
||||
|
||||
if not CONFIG['RELEASE_BUILD']:
|
||||
EXTRA_JS_MODULES += ['BackgroundPageThumbs.jsm']
|
||||
|
|
|
@ -2,18 +2,9 @@
|
|||
# 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/.
|
||||
|
||||
ifndef RELEASE_BUILD
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_thumbnails_background.js \
|
||||
browser_thumbnails_update.js \
|
||||
thumbnails_background.sjs \
|
||||
thumbnails_update.sjs \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
MOCHITEST_BROWSER_FILES += \
|
||||
browser_thumbnails_background_crash.js \
|
||||
thumbnails_crash_content_helper.js \
|
||||
$(NULL)
|
||||
endif
|
||||
endif
|
||||
|
|
|
@ -5,7 +5,10 @@ support-files =
|
|||
background_red_scroll.html
|
||||
head.js
|
||||
privacy_cache_control.sjs
|
||||
thumbnails_background.sjs
|
||||
thumbnails_update.sjs
|
||||
|
||||
[browser_thumbnails_background.js]
|
||||
[browser_thumbnails_bug726727.js]
|
||||
[browser_thumbnails_bug727765.js]
|
||||
[browser_thumbnails_bug818225.js]
|
||||
|
@ -15,3 +18,4 @@ support-files =
|
|||
[browser_thumbnails_redirect.js]
|
||||
[browser_thumbnails_storage.js]
|
||||
[browser_thumbnails_storage_migrate3.js]
|
||||
[browser_thumbnails_update.js]
|
||||
|
|
|
@ -0,0 +1,851 @@
|
|||
/* 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 {Cc, Ci, Cu, Cr} = require("chrome");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const events = require("sdk/event/core");
|
||||
const protocol = require("devtools/server/protocol");
|
||||
|
||||
const { on, once, off, emit } = events;
|
||||
const { method, Arg, Option, RetVal } = protocol;
|
||||
|
||||
const WEBGL_CONTEXT_NAMES = ["webgl", "experimental-webgl", "moz-webgl"];
|
||||
const HIGHLIGHT_FRAG_SHADER = [
|
||||
"precision lowp float;",
|
||||
"void main() {",
|
||||
"gl_FragColor.rgba = vec4(%color);",
|
||||
"}"
|
||||
].join("\n");
|
||||
|
||||
exports.register = function(handle) {
|
||||
handle.addTabActor(WebGLActor, "webglActor");
|
||||
}
|
||||
|
||||
exports.unregister = function(handle) {
|
||||
handle.removeTabActor(WebGLActor);
|
||||
}
|
||||
|
||||
/**
|
||||
* A WebGL Shader contributing to building a WebGL Program.
|
||||
* You can either retrieve, or compile the source of a shader, which will
|
||||
* automatically inflict the necessary changes to the WebGL state.
|
||||
*/
|
||||
let ShaderActor = protocol.ActorClass({
|
||||
typeName: "gl-shader",
|
||||
initialize: function(conn, id) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the source code for this shader.
|
||||
*/
|
||||
getText: method(function() {
|
||||
return this.text;
|
||||
}, {
|
||||
response: { text: RetVal("string") }
|
||||
}),
|
||||
|
||||
/**
|
||||
* Sets and compiles new source code for this shader.
|
||||
*/
|
||||
compile: method(function(text) {
|
||||
// Get the shader and corresponding program to change via the WebGL proxy.
|
||||
let { context, shader, program, observer: { proxy } } = this;
|
||||
|
||||
// Get the new shader source to inject.
|
||||
let oldText = this.text;
|
||||
let newText = text;
|
||||
|
||||
// Overwrite the shader's source.
|
||||
let error = proxy.call("compileShader", context, program, shader, this.text = newText);
|
||||
|
||||
// If something went wrong, revert to the previous shader.
|
||||
if (error.compile || error.link) {
|
||||
proxy.call("compileShader", context, program, shader, this.text = oldText);
|
||||
return error;
|
||||
}
|
||||
return undefined;
|
||||
}, {
|
||||
request: { text: Arg(0, "string") },
|
||||
response: { error: RetVal("nullable:json") }
|
||||
})
|
||||
});
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the ShaderActor.
|
||||
*/
|
||||
let ShaderFront = protocol.FrontClass(ShaderActor, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* A WebGL program is composed (at the moment, analogue to OpenGL ES 2.0)
|
||||
* of two shaders: a vertex shader and a fragment shader.
|
||||
*/
|
||||
let ProgramActor = protocol.ActorClass({
|
||||
typeName: "gl-program",
|
||||
initialize: function(conn, id) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this._shaderActorsCache = { vertex: null, fragment: null };
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the vertex shader linked to this program. This method guarantees
|
||||
* a single actor instance per shader.
|
||||
*/
|
||||
getVertexShader: method(function() {
|
||||
return this._getShaderActor("vertex");
|
||||
}, {
|
||||
response: { shader: RetVal("gl-shader") }
|
||||
}),
|
||||
|
||||
/**
|
||||
* Gets the fragment shader linked to this program. This method guarantees
|
||||
* a single actor instance per shader.
|
||||
*/
|
||||
getFragmentShader: method(function() {
|
||||
return this._getShaderActor("fragment");
|
||||
}, {
|
||||
response: { shader: RetVal("gl-shader") }
|
||||
}),
|
||||
|
||||
/**
|
||||
* Replaces this program's fragment shader with an temporary
|
||||
* easy-to-distinguish alternative. See HIGHLIGHT_FRAG_SHADER.
|
||||
*/
|
||||
highlight: method(function(color) {
|
||||
let shaderActor = this._getShaderActor("fragment");
|
||||
let oldText = shaderActor.text;
|
||||
let newText = HIGHLIGHT_FRAG_SHADER.replace("%color", color)
|
||||
shaderActor.compile(newText);
|
||||
shaderActor.text = oldText;
|
||||
}, {
|
||||
request: { color: Arg(0, "array:string") },
|
||||
oneway: true
|
||||
}),
|
||||
|
||||
/**
|
||||
* Reverts this program's fragment shader to the latest user-defined source.
|
||||
*/
|
||||
unhighlight: method(function() {
|
||||
let shaderActor = this._getShaderActor("fragment");
|
||||
shaderActor.compile(shaderActor.text);
|
||||
}, {
|
||||
oneway: true
|
||||
}),
|
||||
|
||||
/**
|
||||
* Returns a cached ShaderActor instance based on the required shader type.
|
||||
*
|
||||
* @param string type
|
||||
* Either "vertex" or "fragment".
|
||||
* @return ShaderActor
|
||||
* The respective shader actor instance.
|
||||
*/
|
||||
_getShaderActor: function(type) {
|
||||
if (this._shaderActorsCache[type]) {
|
||||
return this._shaderActorsCache[type];
|
||||
}
|
||||
|
||||
let shaderActor = new ShaderActor(this.conn);
|
||||
shaderActor.context = this.context;
|
||||
shaderActor.observer = this.observer;
|
||||
shaderActor.program = this.program;
|
||||
shaderActor.shader = this.shadersData[type].ref;
|
||||
shaderActor.text = this.shadersData[type].text;
|
||||
|
||||
return this._shaderActorsCache[type] = shaderActor;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the ProgramActor.
|
||||
*/
|
||||
let ProgramFront = protocol.FrontClass(ProgramActor, {
|
||||
initialize: function(client, form) {
|
||||
protocol.Front.prototype.initialize.call(this, client, form);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The WebGL Actor handles simple interaction with a WebGL context via a few
|
||||
* high-level methods. After instantiating this actor, you'll need to set it
|
||||
* up by calling setup().
|
||||
*/
|
||||
let WebGLActor = exports.WebGLActor = protocol.ActorClass({
|
||||
typeName: "webgl",
|
||||
initialize: function(conn, tabActor) {
|
||||
protocol.Actor.prototype.initialize.call(this, conn);
|
||||
this.tabActor = tabActor;
|
||||
this._onGlobalCreated = this._onGlobalCreated.bind(this);
|
||||
this._onProgramLinked = this._onProgramLinked.bind(this);
|
||||
},
|
||||
destroy: function(conn) {
|
||||
protocol.Actor.prototype.destroy.call(this, conn);
|
||||
this.finalize();
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts waiting for the current tab actor's document global to be
|
||||
* created, in order to instrument the Canvas context and become
|
||||
* aware of everything the content does WebGL-wise.
|
||||
*
|
||||
* See ContentObserver and WebGLInstrumenter for more details.
|
||||
*/
|
||||
setup: method(function() {
|
||||
if (this._initialized) {
|
||||
return;
|
||||
}
|
||||
this._initialized = true;
|
||||
this._contentObserver = new ContentObserver(this.tabActor);
|
||||
this._webglObserver = new WebGLObserver();
|
||||
on(this._contentObserver, "global-created", this._onGlobalCreated);
|
||||
on(this._webglObserver, "program-linked", this._onProgramLinked);
|
||||
|
||||
this.tabActor.window.location.reload();
|
||||
}, {
|
||||
oneway: true
|
||||
}),
|
||||
|
||||
/**
|
||||
* Stops listening for document global changes and puts this actor
|
||||
* to hibernation. This method is called automatically just before the
|
||||
* actor is destroyed.
|
||||
*/
|
||||
finalize: method(function() {
|
||||
if (!this._initialized) {
|
||||
return;
|
||||
}
|
||||
this._initialized = false;
|
||||
this._contentObserver.stopListening();
|
||||
off(this._contentObserver, "global-created", this._onGlobalCreated);
|
||||
off(this._webglObserver, "program-linked", this._onProgramLinked);
|
||||
}, {
|
||||
oneway: true
|
||||
}),
|
||||
|
||||
/**
|
||||
* Events emitted by this actor. The "program-linked" event is fired
|
||||
* every time a WebGL program was linked with its respective two shaders.
|
||||
*/
|
||||
events: {
|
||||
"program-linked": {
|
||||
type: "programLinked",
|
||||
program: Arg(0, "gl-program")
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked whenever the current tab actor's document global is created.
|
||||
*/
|
||||
_onGlobalCreated: function(window) {
|
||||
WebGLInstrumenter.handle(window, this._webglObserver);
|
||||
},
|
||||
|
||||
/**
|
||||
* Invoked whenever the current WebGL context links a program.
|
||||
*/
|
||||
_onProgramLinked: function(gl, program, shaders) {
|
||||
let observer = this._webglObserver;
|
||||
let shadersData = { vertex: null, fragment: null };
|
||||
|
||||
for (let shader of shaders) {
|
||||
let text = observer.cache.call("getShaderInfo", shader);
|
||||
let data = { ref: shader, text: text };
|
||||
|
||||
// Make sure the shader data object always contains the vertex shader
|
||||
// first, and the fragment shader second. There are no guarantees that
|
||||
// the compilation order of shaders in the debuggee is always the same.
|
||||
if (gl.getShaderParameter(shader, gl.SHADER_TYPE) == gl.VERTEX_SHADER) {
|
||||
shadersData.vertex = data;
|
||||
} else {
|
||||
shadersData.fragment = data;
|
||||
}
|
||||
}
|
||||
|
||||
let programActor = new ProgramActor(this.conn);
|
||||
programActor.context = gl;
|
||||
programActor.observer = observer;
|
||||
programActor.program = program;
|
||||
programActor.shadersData = shadersData;
|
||||
|
||||
events.emit(this, "program-linked", programActor);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* The corresponding Front object for the WebGLActor.
|
||||
*/
|
||||
let WebGLFront = exports.WebGLFront = protocol.FrontClass(WebGLActor, {
|
||||
initialize: function(client, { webglActor }) {
|
||||
protocol.Front.prototype.initialize.call(this, client, { actor: webglActor });
|
||||
client.addActorPool(this);
|
||||
this.manage(this);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Handles adding an observer for the creation of content document globals,
|
||||
* event sent immediately after a web content document window has been set up,
|
||||
* but before any script code has been executed. This will allow us to
|
||||
* instrument the HTMLCanvasElement with the appropriate inspection methods.
|
||||
*/
|
||||
function ContentObserver(tabActor) {
|
||||
this._contentWindow = tabActor.browser.contentWindow;
|
||||
this._onContentGlobalCreated = this._onContentGlobalCreated.bind(this);
|
||||
this.startListening();
|
||||
}
|
||||
|
||||
ContentObserver.prototype = {
|
||||
/**
|
||||
* Starts listening for the required observer messages.
|
||||
*/
|
||||
startListening: function() {
|
||||
Services.obs.addObserver(
|
||||
this._onContentGlobalCreated, "content-document-global-created", false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops listening for the required observer messages.
|
||||
*/
|
||||
stopListening: function() {
|
||||
Services.obs.removeObserver(
|
||||
this._onContentGlobalCreated, "content-document-global-created", false);
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired immediately after a web content document window has been set up.
|
||||
*/
|
||||
_onContentGlobalCreated: function(subject, topic, data) {
|
||||
if (subject == this._contentWindow) {
|
||||
emit(this, "global-created", subject);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Instruments a HTMLCanvasElement with the appropriate inspection methods.
|
||||
*/
|
||||
let WebGLInstrumenter = {
|
||||
/**
|
||||
* Overrides the getContext method in the HTMLCanvasElement prototype.
|
||||
*
|
||||
* @param nsIDOMWindow window
|
||||
* The window to perform the instrumentation in.
|
||||
* @param WebGLObserver observer
|
||||
* The observer watching function calls in the context.
|
||||
*/
|
||||
handle: function(window, observer) {
|
||||
let self = this;
|
||||
|
||||
let canvasElem = XPCNativeWrapper.unwrap(window.HTMLCanvasElement);
|
||||
let canvasPrototype = canvasElem.prototype;
|
||||
let originalGetContext = canvasPrototype.getContext;
|
||||
|
||||
/**
|
||||
* Returns a drawing context on the canvas, or null if the context ID is
|
||||
* not supported. This override creates an observer for the targeted context
|
||||
* type and instruments specific functions in the targeted context instance.
|
||||
*/
|
||||
canvasPrototype.getContext = function(name, options) {
|
||||
// Make sure a context was able to be created.
|
||||
let context = originalGetContext.call(this, name, options);
|
||||
if (!context) {
|
||||
return context;
|
||||
}
|
||||
// Make sure a WebGL (not a 2D) context will be instrumented.
|
||||
if (WEBGL_CONTEXT_NAMES.indexOf(name) == -1) {
|
||||
return context;
|
||||
}
|
||||
|
||||
// Link our observer to the new WebGL context methods.
|
||||
for (let { timing, callback, functions } of self._methods) {
|
||||
for (let func of functions) {
|
||||
self._instrument(observer, context, func, timing, callback);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the decorated context back to the content consumer, which
|
||||
// will continue using it normally.
|
||||
return context;
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Overrides a specific method in a HTMLCanvasElement context.
|
||||
*
|
||||
* @param WebGLObserver observer
|
||||
* The observer watching function calls in the context.
|
||||
* @param WebGLRenderingContext context
|
||||
* The targeted context instance.
|
||||
* @param string funcName
|
||||
* The function to override.
|
||||
* @param string timing [optional]
|
||||
* When to issue the callback in relation to the actual context
|
||||
* function call. Availalble values are "before" and "after" (default).
|
||||
* @param string callbackName [optional]
|
||||
* A custom callback function name in the observer. If unspecified,
|
||||
* it will default to the name of the function to override.
|
||||
*/
|
||||
_instrument: function(observer, context, funcName, timing, callbackName) {
|
||||
let originalFunc = context[funcName];
|
||||
|
||||
context[funcName] = function() {
|
||||
let glArgs = Array.slice(arguments);
|
||||
let glResult, glBreak;
|
||||
|
||||
if (timing == "before" && !observer.suppressHandlers) {
|
||||
glBreak = observer.call(callbackName || funcName, context, glArgs);
|
||||
if (glBreak) return undefined;
|
||||
}
|
||||
|
||||
glResult = originalFunc.apply(this, glArgs);
|
||||
|
||||
if (timing == "after" && !observer.suppressHandlers) {
|
||||
glBreak = observer.call(callbackName || funcName, context, glArgs, glResult);
|
||||
if (glBreak) return undefined;
|
||||
}
|
||||
|
||||
return glResult;
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Override mappings for WebGL methods.
|
||||
*/
|
||||
_methods: [{
|
||||
timing: "after",
|
||||
functions: [
|
||||
"linkProgram", "getAttribLocation", "getUniformLocation"
|
||||
]
|
||||
}, {
|
||||
timing: "before",
|
||||
callback: "toggleVertexAttribArray",
|
||||
functions: [
|
||||
"enableVertexAttribArray", "disableVertexAttribArray"
|
||||
]
|
||||
}, {
|
||||
timing: "before",
|
||||
callback: "attribute_",
|
||||
functions: [
|
||||
"vertexAttrib1f", "vertexAttrib2f", "vertexAttrib3f", "vertexAttrib4f",
|
||||
"vertexAttrib1fv", "vertexAttrib2fv", "vertexAttrib3fv", "vertexAttrib4fv",
|
||||
"vertexAttribPointer"
|
||||
]
|
||||
}, {
|
||||
timing: "before",
|
||||
callback: "uniform_",
|
||||
functions: [
|
||||
"uniform1i", "uniform2i", "uniform3i", "uniform4i",
|
||||
"uniform1f", "uniform2f", "uniform3f", "uniform4f",
|
||||
"uniform1iv", "uniform2iv", "uniform3iv", "uniform4iv",
|
||||
"uniform1fv", "uniform2fv", "uniform3fv", "uniform4fv",
|
||||
"uniformMatrix2fv", "uniformMatrix3fv", "uniformMatrix4fv"
|
||||
]
|
||||
}]
|
||||
// TODO: It'd be a good idea to handle other functions as well:
|
||||
// - getActiveUniform
|
||||
// - getUniform
|
||||
// - getActiveAttrib
|
||||
// - getVertexAttrib
|
||||
};
|
||||
|
||||
/**
|
||||
* An observer that captures a WebGL context's method calls.
|
||||
*/
|
||||
function WebGLObserver() {
|
||||
this.cache = new WebGLCache(this);
|
||||
this.proxy = new WebGLProxy(this);
|
||||
}
|
||||
|
||||
WebGLObserver.prototype = {
|
||||
/**
|
||||
* Set this flag to true to stop observing any context function calls.
|
||||
*/
|
||||
suppressHandlers: false,
|
||||
|
||||
/**
|
||||
* Called immediately *after* 'linkProgram' is requested in the context.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context initiating this call.
|
||||
* @param array glArgs
|
||||
* Overridable arguments with which the function is called.
|
||||
* @param void glResult
|
||||
* The returned value of the original function call.
|
||||
*/
|
||||
linkProgram: function(gl, glArgs, glResult) {
|
||||
let program = glArgs[0];
|
||||
let shaders = gl.getAttachedShaders(program);
|
||||
|
||||
for (let shader of shaders) {
|
||||
let source = gl.getShaderSource(shader);
|
||||
this.cache.call("addShaderInfo", shader, source);
|
||||
}
|
||||
|
||||
emit(this, "program-linked", gl, program, shaders);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called immediately *after* 'getAttribLocation' is requested in the context.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context initiating this call.
|
||||
* @param array glArgs
|
||||
* Overridable arguments with which the function is called.
|
||||
* @param GLint glResult
|
||||
* The returned value of the original function call.
|
||||
*/
|
||||
getAttribLocation: function(gl, glArgs, glResult) {
|
||||
let [program, name] = glArgs;
|
||||
this.cache.call("addAttribute", program, name, glResult);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called immediately *after* 'getUniformLocation' is requested in the context.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context initiating this call.
|
||||
* @param array glArgs
|
||||
* Overridable arguments with which the function is called.
|
||||
* @param WebGLUniformLocation glResult
|
||||
* The returned value of the original function call.
|
||||
*/
|
||||
getUniformLocation: function(gl, glArgs, glResult) {
|
||||
let [program, name] = glArgs;
|
||||
this.cache.call("addUniform", program, name, glResult);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called immediately *before* 'enableVertexAttribArray' or
|
||||
* 'disableVertexAttribArray'is requested in the context.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context initiating this call.
|
||||
* @param array glArgs
|
||||
* Overridable arguments with which the function is called.
|
||||
*/
|
||||
toggleVertexAttribArray: function(gl, glArgs) {
|
||||
glArgs[0] = this.cache.call("getCurrentAttributeLocation", glArgs[0]);
|
||||
return glArgs[0] < 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called immediately *before* 'attribute_' is requested in the context.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context initiating this call.
|
||||
* @param array glArgs
|
||||
* Overridable arguments with which the function is called.
|
||||
*/
|
||||
attribute_: function(gl, glArgs) {
|
||||
glArgs[0] = this.cache.call("getCurrentAttributeLocation", glArgs[0]);
|
||||
return glArgs[0] < 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called immediately *before* 'uniform_' is requested in the context.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context initiating this call.
|
||||
* @param array glArgs
|
||||
* Overridable arguments with which the function is called.
|
||||
*/
|
||||
uniform_: function(gl, glArgs) {
|
||||
glArgs[0] = this.cache.call("getCurrentUniformLocation", glArgs[0]);
|
||||
return !glArgs[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes a function in this object.
|
||||
* This method makes sure that any handlers in the context observer are
|
||||
* suppressed, hence stopping observing any context function calls.
|
||||
*
|
||||
* @param string funcName
|
||||
* The function to call.
|
||||
*/
|
||||
call: function(funcName, ...args) {
|
||||
let prevState = this.suppressHandlers;
|
||||
|
||||
this.suppressHandlers = true;
|
||||
let result = this[funcName].apply(this, args);
|
||||
this.suppressHandlers = prevState;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache storing WebGL state, like shaders, attributes or uniforms.
|
||||
*
|
||||
* @param WebGLObserver observer
|
||||
* The observer for the target context.
|
||||
*/
|
||||
function WebGLCache(observer) {
|
||||
this._observer = observer;
|
||||
|
||||
this._shaders = new Map();
|
||||
this._attributes = [];
|
||||
this._uniforms = [];
|
||||
this._attributesBridge = new Map();
|
||||
this._uniformsBridge = new Map();
|
||||
}
|
||||
|
||||
WebGLCache.prototype = {
|
||||
/**
|
||||
* Adds shader information to the cache.
|
||||
*
|
||||
* @param WebGLShader shader
|
||||
* The shader for which the source is to be cached. If the shader
|
||||
* was already cached, nothing happens.
|
||||
* @param string text
|
||||
* The current shader text.
|
||||
*/
|
||||
_addShaderInfo: function(shader, text) {
|
||||
if (!this._shaders.has(shader)) {
|
||||
this._shaders.set(shader, text);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets shader information from the cache.
|
||||
*
|
||||
* @param WebGLShader shader
|
||||
* The shader for which the source was cached.
|
||||
* @return object | null
|
||||
* The original shader source, or null if there's a cache miss.
|
||||
*/
|
||||
_getShaderInfo: function(shader) {
|
||||
return this._shaders.get(shader);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds an attribute to the cache.
|
||||
*
|
||||
* @param WebGLProgram program
|
||||
* The program for which the attribute is bound. If the attribute
|
||||
* was already cached, nothing happens.
|
||||
* @param string name
|
||||
* The attribute name.
|
||||
* @param GLint value
|
||||
* The attribute value.
|
||||
*/
|
||||
_addAttribute: function(program, name, value) {
|
||||
let isCached = this._attributes.some(e => e.program == program && e.name == name);
|
||||
if (isCached || value < 0) {
|
||||
return;
|
||||
}
|
||||
let attributeInfo = {
|
||||
program: program,
|
||||
name: name,
|
||||
value: value
|
||||
};
|
||||
this._attributes.push(attributeInfo);
|
||||
this._attributesBridge.set(value, attributeInfo);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a uniform to the cache.
|
||||
*
|
||||
* @param WebGLProgram program
|
||||
* The program for which the uniform is bound. If the uniform
|
||||
* was already cached, nothing happens.
|
||||
* @param string name
|
||||
* The uniform name.
|
||||
* @param WebGLUniformLocation value
|
||||
* The uniform value.
|
||||
*/
|
||||
_addUniform: function(program, name, value) {
|
||||
let isCached = this._uniforms.some(e => e.program == program && e.name == name);
|
||||
if (isCached || !value) {
|
||||
return;
|
||||
}
|
||||
let uniformInfo = {
|
||||
program: program,
|
||||
name: name,
|
||||
value: value
|
||||
};
|
||||
this._uniforms.push(uniformInfo);
|
||||
this._uniformsBridge.set(new XPCNativeWrapper(value), uniformInfo);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all the cached attributes for a specific program.
|
||||
*
|
||||
* @param WebGLProgram program
|
||||
* The program for which the attributes are bound.
|
||||
* @return array
|
||||
* A list containing information about all the attributes.
|
||||
*/
|
||||
_getAttributesForProgram: function(program) {
|
||||
return this._attributes.filter(e => e.program == program);
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all the cached uniforms for a specific program.
|
||||
*
|
||||
* @param WebGLProgram program
|
||||
* The program for which the uniforms are bound.
|
||||
* @return array
|
||||
* A list containing information about all the uniforms.
|
||||
*/
|
||||
_getUniformsForProgram: function(program) {
|
||||
return this._uniforms.filter(e => e.program == program);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the attribute locations for a specific program.
|
||||
* This is necessary, for example, when the shader is relinked and all the
|
||||
* attribute locations become obsolete.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context owning the program.
|
||||
* @param WebGLProgram program
|
||||
* The program for which the attributes need updating.
|
||||
*/
|
||||
_updateAttributesForProgram: function(gl, program) {
|
||||
let dirty = this._attributes.filter(e => e.program == program);
|
||||
dirty.forEach(e => e.value = gl.getAttribLocation(program, e.name));
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the uniform locations for a specific program.
|
||||
* This is necessary, for example, when the shader is relinked and all the
|
||||
* uniform locations become obsolete.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context owning the program.
|
||||
* @param WebGLProgram program
|
||||
* The program for which the uniforms need updating.
|
||||
*/
|
||||
_updateUniformsForProgram: function(gl, program) {
|
||||
let dirty = this._uniforms.filter(e => e.program == program);
|
||||
dirty.forEach(e => e.value = gl.getUniformLocation(program, e.name));
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the actual attribute location in a specific program.
|
||||
* When relinked, all the attribute locations become obsolete and are updated
|
||||
* in the cache. This method returns the (current) real attribute location.
|
||||
*
|
||||
* @param GLint initialValue
|
||||
* The initial attribute value.
|
||||
* @return GLint
|
||||
* The current attribute value, or the initial value if it's already
|
||||
* up to date with its corresponding program.
|
||||
*/
|
||||
_getCurrentAttributeLocation: function(initialValue) {
|
||||
let currentInfo = this._attributesBridge.get(initialValue);
|
||||
return currentInfo ? currentInfo.value : initialValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the actual uniform location in a specific program.
|
||||
* When relinked, all the uniform locations become obsolete and are updated
|
||||
* in the cache. This method returns the (current) real uniform location.
|
||||
*
|
||||
* @param WebGLUniformLocation initialValue
|
||||
* The initial uniform value.
|
||||
* @return WebGLUniformLocation
|
||||
* The current uniform value, or the initial value if it's already
|
||||
* up to date with its corresponding program.
|
||||
*/
|
||||
_getCurrentUniformLocation: function(initialValue) {
|
||||
let currentInfo = this._uniformsBridge.get(initialValue);
|
||||
return currentInfo ? currentInfo.value : initialValue;
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes a function in this object.
|
||||
* This method makes sure that any handlers in the context observer are
|
||||
* suppressed, hence stopping observing any context function calls.
|
||||
*
|
||||
* @param string funcName
|
||||
* The function to call.
|
||||
* @return any
|
||||
* The called function result.
|
||||
*/
|
||||
call: function(funcName, ...aArgs) {
|
||||
let prevState = this._observer.suppressHandlers;
|
||||
|
||||
this._observer.suppressHandlers = true;
|
||||
let result = this["_" + funcName].apply(this, aArgs);
|
||||
this._observer.suppressHandlers = prevState;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A mechanism for injecting or qureying state into/from a WebGL context.
|
||||
*
|
||||
* @param WebGLObserver observer
|
||||
* The observer for the target context.
|
||||
*/
|
||||
function WebGLProxy(observer) {
|
||||
this._observer = observer;
|
||||
}
|
||||
|
||||
WebGLProxy.prototype = {
|
||||
get cache() this._observer.cache,
|
||||
|
||||
/**
|
||||
* Changes a shader's source code and relinks the respective program.
|
||||
*
|
||||
* @param WebGLRenderingContext gl
|
||||
* The WebGL context owning the program.
|
||||
* @param WebGLProgram program
|
||||
* The program who's linked shader is to be modified.
|
||||
* @param WebGLShader shader
|
||||
* The shader to be modified.
|
||||
* @param string text
|
||||
* The new shader source code.
|
||||
* @return string
|
||||
* The shader's compilation and linking status.
|
||||
*/
|
||||
_compileShader: function(gl, program, shader, text) {
|
||||
gl.shaderSource(shader, text);
|
||||
gl.compileShader(shader);
|
||||
gl.linkProgram(program);
|
||||
|
||||
let error = { compile: "", link: "" };
|
||||
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
error.compile = gl.getShaderInfoLog(shader);
|
||||
}
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
error.link = gl.getShaderInfoLog(shader);
|
||||
}
|
||||
|
||||
this.cache.call("updateAttributesForProgram", gl, program);
|
||||
this.cache.call("updateUniformsForProgram", gl, program);
|
||||
|
||||
return error;
|
||||
},
|
||||
|
||||
/**
|
||||
* Executes a function in this object.
|
||||
* This method makes sure that any handlers in the context observer are
|
||||
* suppressed, hence stopping observing any context function calls.
|
||||
*
|
||||
* @param string funcName
|
||||
* The function to call.
|
||||
* @return any
|
||||
* The called function result.
|
||||
*/
|
||||
call: function(funcName, ...aArgs) {
|
||||
let prevState = this._observer.suppressHandlers;
|
||||
|
||||
this._observer.suppressHandlers = true;
|
||||
let result = this["_" + funcName].apply(this, aArgs);
|
||||
this._observer.suppressHandlers = prevState;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
|
@ -366,6 +366,7 @@ var DebuggerServer = {
|
|||
this.addActors("resource://gre/modules/devtools/server/actors/styleeditor.js");
|
||||
this.addActors("resource://gre/modules/devtools/server/actors/webapps.js");
|
||||
this.registerModule("devtools/server/actors/inspector");
|
||||
this.registerModule("devtools/server/actors/webgl");
|
||||
this.registerModule("devtools/server/actors/tracer");
|
||||
this.registerModule("devtools/server/actors/device");
|
||||
},
|
||||
|
@ -384,6 +385,7 @@ var DebuggerServer = {
|
|||
this.addActors("resource://gre/modules/devtools/server/actors/gcli.js");
|
||||
this.addActors("resource://gre/modules/devtools/server/actors/styleeditor.js");
|
||||
this.registerModule("devtools/server/actors/inspector");
|
||||
this.registerModule("devtools/server/actors/webgl");
|
||||
}
|
||||
if (!("ContentAppActor" in DebuggerServer)) {
|
||||
this.addActors("resource://gre/modules/devtools/server/actors/childtab.js");
|
||||
|
|
|
@ -102,6 +102,7 @@ const KEY_APP_SYSTEM_LOCAL = "app-system-local";
|
|||
const KEY_APP_SYSTEM_SHARE = "app-system-share";
|
||||
const KEY_APP_SYSTEM_USER = "app-system-user";
|
||||
|
||||
const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions";
|
||||
const XPI_PERMISSION = "install";
|
||||
|
||||
const RDFURI_INSTALL_MANIFEST_ROOT = "urn:mozilla:install-manifest";
|
||||
|
@ -1952,6 +1953,7 @@ var XPIProvider = {
|
|||
|
||||
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_APP_VERSION, this, false);
|
||||
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, this, false);
|
||||
Services.obs.addObserver(this, NOTIFICATION_FLUSH_PERMISSIONS, false);
|
||||
|
||||
let flushCaches = this.checkForChanges(aAppChanged, aOldAppVersion,
|
||||
aOldPlatformVersion);
|
||||
|
@ -3322,10 +3324,6 @@ var XPIProvider = {
|
|||
aOldPlatformVersion) {
|
||||
LOG("checkForChanges");
|
||||
|
||||
// Import the website installation permissions if the application has changed
|
||||
if (aAppChanged !== false)
|
||||
this.importPermissions();
|
||||
|
||||
// Keep track of whether and why we need to open and update the database at
|
||||
// startup time.
|
||||
let updateReasons = [];
|
||||
|
@ -3521,6 +3519,7 @@ var XPIProvider = {
|
|||
if (aUri.schemeIs("chrome") || aUri.schemeIs("file"))
|
||||
return true;
|
||||
|
||||
this.importPermissions();
|
||||
|
||||
let permission = Services.perms.testPermission(aUri, XPI_PERMISSION);
|
||||
if (permission == Ci.nsIPermissionManager.DENY_ACTION)
|
||||
|
@ -3849,15 +3848,24 @@ var XPIProvider = {
|
|||
* @see nsIObserver
|
||||
*/
|
||||
observe: function XPI_observe(aSubject, aTopic, aData) {
|
||||
switch (aData) {
|
||||
case PREF_EM_MIN_COMPAT_APP_VERSION:
|
||||
case PREF_EM_MIN_COMPAT_PLATFORM_VERSION:
|
||||
this.minCompatibleAppVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_APP_VERSION,
|
||||
null);
|
||||
this.minCompatiblePlatformVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION,
|
||||
null);
|
||||
this.updateAddonAppDisabledStates();
|
||||
break;
|
||||
if (aTopic == NOTIFICATION_FLUSH_PERMISSIONS) {
|
||||
if (!aData || aData == XPI_PERMISSION) {
|
||||
this.importPermissions();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (aTopic == "nsPref:changed") {
|
||||
switch (aData) {
|
||||
case PREF_EM_MIN_COMPAT_APP_VERSION:
|
||||
case PREF_EM_MIN_COMPAT_PLATFORM_VERSION:
|
||||
this.minCompatibleAppVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_APP_VERSION,
|
||||
null);
|
||||
this.minCompatiblePlatformVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION,
|
||||
null);
|
||||
this.updateAddonAppDisabledStates();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that xpinstall.[whitelist|blacklist].add preferences are emptied when
|
||||
// converted into permissions on startup with new profile
|
||||
|
||||
const PREF_XPI_WHITELIST_PERMISSIONS = "xpinstall.whitelist.add";
|
||||
const PREF_XPI_BLACKLIST_PERMISSIONS = "xpinstall.blacklist.add";
|
||||
|
||||
function run_test() {
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
|
||||
|
||||
// Create own preferences to test
|
||||
Services.prefs.setCharPref("xpinstall.whitelist.add.EMPTY", "");
|
||||
Services.prefs.setCharPref("xpinstall.whitelist.add.TEST", "whitelist.example.com");
|
||||
Services.prefs.setCharPref("xpinstall.blacklist.add.EMPTY", "");
|
||||
Services.prefs.setCharPref("xpinstall.blacklist.add.TEST", "blacklist.example.com");
|
||||
|
||||
// Get list of preferences to check
|
||||
var whitelistPreferences = Services.prefs.getChildList(PREF_XPI_WHITELIST_PERMISSIONS, {});
|
||||
var blacklistPreferences = Services.prefs.getChildList(PREF_XPI_BLACKLIST_PERMISSIONS, {});
|
||||
var preferences = whitelistPreferences.concat(blacklistPreferences);
|
||||
|
||||
startupManager();
|
||||
|
||||
// Check preferences were emptied
|
||||
preferences.forEach(function(aPreference) {
|
||||
try {
|
||||
do_check_eq(Services.prefs.getCharPref(aPreference), "");
|
||||
}
|
||||
catch (e) {
|
||||
// Successfully emptied
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests that xpinstall.[whitelist|blacklist].add preferences are emptied when
|
||||
// converted into permissions.
|
||||
|
||||
const PREF_XPI_WHITELIST_PERMISSIONS = "xpinstall.whitelist.add";
|
||||
const PREF_XPI_BLACKLIST_PERMISSIONS = "xpinstall.blacklist.add";
|
||||
|
||||
function do_check_permission_prefs(preferences) {
|
||||
// Check preferences were emptied
|
||||
for (let pref of preferences) {
|
||||
try {
|
||||
do_check_eq(Services.prefs.getCharPref(pref), "");
|
||||
}
|
||||
catch (e) {
|
||||
// Successfully emptied
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function clear_imported_preferences_cache() {
|
||||
let scope = Components.utils.import("resource://gre/modules/PermissionsUtils.jsm", {});
|
||||
scope.gImportedPrefBranches.clear();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
|
||||
|
||||
// Create own preferences to test
|
||||
Services.prefs.setCharPref("xpinstall.whitelist.add.EMPTY", "");
|
||||
Services.prefs.setCharPref("xpinstall.whitelist.add.TEST", "whitelist.example.com");
|
||||
Services.prefs.setCharPref("xpinstall.blacklist.add.EMPTY", "");
|
||||
Services.prefs.setCharPref("xpinstall.blacklist.add.TEST", "blacklist.example.com");
|
||||
|
||||
// Get list of preferences to check
|
||||
var whitelistPreferences = Services.prefs.getChildList(PREF_XPI_WHITELIST_PERMISSIONS, {});
|
||||
var blacklistPreferences = Services.prefs.getChildList(PREF_XPI_BLACKLIST_PERMISSIONS, {});
|
||||
var preferences = whitelistPreferences.concat(blacklistPreferences);
|
||||
|
||||
startupManager();
|
||||
|
||||
// Permissions are imported lazily - act as thought we're checking an install,
|
||||
// to trigger on-deman importing of the permissions.
|
||||
let url = Services.io.newURI("http://example.com/file.xpi", null, null);
|
||||
AddonManager.isInstallAllowed("application/x-xpinstall", url);
|
||||
do_check_permission_prefs(preferences);
|
||||
|
||||
|
||||
// Import can also be triggerred by an observer notification by any other area
|
||||
// of code, such as a permissions management UI.
|
||||
|
||||
// First, request to flush all permissions
|
||||
clear_imported_preferences_cache();
|
||||
Services.prefs.setCharPref("xpinstall.whitelist.add.TEST2", "whitelist2.example.com");
|
||||
Services.obs.notifyObservers(null, "flush-pending-permissions", "install");
|
||||
do_check_permission_prefs(preferences);
|
||||
|
||||
// Then, request to flush just install permissions
|
||||
clear_imported_preferences_cache();
|
||||
Services.prefs.setCharPref("xpinstall.whitelist.add.TEST3", "whitelist3.example.com");
|
||||
Services.obs.notifyObservers(null, "flush-pending-permissions", "");
|
||||
do_check_permission_prefs(preferences);
|
||||
|
||||
// And a request to flush some other permissions sholdn't flush install permissions
|
||||
clear_imported_preferences_cache();
|
||||
Services.prefs.setCharPref("xpinstall.whitelist.add.TEST4", "whitelist4.example.com");
|
||||
Services.obs.notifyObservers(null, "flush-pending-permissions", "lolcats");
|
||||
do_check_eq(Services.prefs.getCharPref("xpinstall.whitelist.add.TEST4"), "whitelist4.example.com");
|
||||
}
|
|
@ -122,7 +122,6 @@ fail-if = os == "android"
|
|||
[test_bug569138.js]
|
||||
[test_bug570173.js]
|
||||
[test_bug576735.js]
|
||||
[test_bug578467.js]
|
||||
[test_bug587088.js]
|
||||
[test_bug594058.js]
|
||||
[test_bug595081.js]
|
||||
|
@ -205,6 +204,7 @@ skip-if = os == "android"
|
|||
[test_migrate_max_version.js]
|
||||
[test_onPropertyChanged_appDisabled.js]
|
||||
[test_permissions.js]
|
||||
[test_permissions_prefs.js]
|
||||
[test_plugins.js]
|
||||
[test_pluginchange.js]
|
||||
[test_pluginBlocklistCtp.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче