mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Merge m-c to inbound
This commit is contained in:
commit
be4af0e0fd
@ -58,7 +58,7 @@ let developerHUD = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!DebuggerServer.initialized) {
|
if (!DebuggerServer.initialized) {
|
||||||
RemoteDebugger.start();
|
RemoteDebugger.initServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We instantiate a local debugger connection so that watchers can use our
|
// We instantiate a local debugger connection so that watchers can use our
|
||||||
|
@ -351,7 +351,7 @@ let AdbController = {
|
|||||||
|
|
||||||
// Check if we have a remote debugging session going on. If so, we won't
|
// Check if we have a remote debugging session going on. If so, we won't
|
||||||
// disable adb even if the screen is locked.
|
// disable adb even if the screen is locked.
|
||||||
let isDebugging = RemoteDebugger.isDebugging;
|
let isDebugging = USBRemoteDebugger.isDebugging;
|
||||||
if (this.DEBUG) {
|
if (this.DEBUG) {
|
||||||
this.debug("isDebugging=" + isDebugging);
|
this.debug("isDebugging=" + isDebugging);
|
||||||
}
|
}
|
||||||
@ -432,16 +432,27 @@ SettingsListener.observe("lockscreen.enabled", false,
|
|||||||
AdbController.setLockscreenEnabled.bind(AdbController));
|
AdbController.setLockscreenEnabled.bind(AdbController));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
// Track these separately here so we can determine the correct value for the
|
||||||
|
// pref "devtools.debugger.remote-enabled", which is true when either mode of
|
||||||
|
// using DevTools is enabled.
|
||||||
|
let devtoolsUSB = false;
|
||||||
|
let devtoolsWiFi = false;
|
||||||
|
|
||||||
// Keep the old setting to not break people that won't have updated
|
// Keep the old setting to not break people that won't have updated
|
||||||
// gaia and gecko.
|
// gaia and gecko.
|
||||||
SettingsListener.observe('devtools.debugger.remote-enabled', false, function(value) {
|
SettingsListener.observe('devtools.debugger.remote-enabled', false,
|
||||||
Services.prefs.setBoolPref('devtools.debugger.remote-enabled', value);
|
function(value) {
|
||||||
|
devtoolsUSB = value;
|
||||||
|
Services.prefs.setBoolPref('devtools.debugger.remote-enabled',
|
||||||
|
devtoolsUSB || devtoolsWiFi);
|
||||||
// This preference is consulted during startup
|
// This preference is consulted during startup
|
||||||
Services.prefs.savePrefFile(null);
|
Services.prefs.savePrefFile(null);
|
||||||
try {
|
try {
|
||||||
value ? RemoteDebugger.start() : RemoteDebugger.stop();
|
value ? USBRemoteDebugger.start() : USBRemoteDebugger.stop();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
dump("Error while initializing devtools: " + e + "\n" + e.stack + "\n");
|
dump("Error while initializing USB devtools: "
|
||||||
|
+ e + "\n" + e.stack + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
@ -455,16 +466,18 @@ SettingsListener.observe('debugger.remote-mode', false, function(value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devtoolsUSB = value == 'adb-devtools';
|
||||||
Services.prefs.setBoolPref('devtools.debugger.remote-enabled',
|
Services.prefs.setBoolPref('devtools.debugger.remote-enabled',
|
||||||
value == 'adb-devtools');
|
devtoolsUSB || devtoolsWiFi);
|
||||||
// This preference is consulted during startup
|
// This preference is consulted during startup
|
||||||
Services.prefs.savePrefFile(null);
|
Services.prefs.savePrefFile(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
(value == 'adb-devtools') ? RemoteDebugger.start()
|
(value == 'adb-devtools') ? USBRemoteDebugger.start()
|
||||||
: RemoteDebugger.stop();
|
: USBRemoteDebugger.stop();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
dump("Error while initializing devtools: " + e + "\n" + e.stack + "\n");
|
dump("Error while initializing USB devtools: "
|
||||||
|
+ e + "\n" + e.stack + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
#ifdef MOZ_WIDGET_GONK
|
||||||
@ -472,6 +485,26 @@ SettingsListener.observe('debugger.remote-mode', false, function(value) {
|
|||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SettingsListener.observe('devtools.remote.wifi.enabled', false,
|
||||||
|
function(value) {
|
||||||
|
devtoolsWiFi = value;
|
||||||
|
Services.prefs.setBoolPref('devtools.debugger.remote-enabled',
|
||||||
|
devtoolsUSB || devtoolsWiFi);
|
||||||
|
// Allow remote debugging on non-local interfaces when WiFi debug is enabled
|
||||||
|
// TODO: Bug 1034411: Lock down to WiFi interface, instead of all interfaces
|
||||||
|
Services.prefs.setBoolPref('devtools.debugger.force-local', !value);
|
||||||
|
// This preference is consulted during startup
|
||||||
|
Services.prefs.savePrefFile(null);
|
||||||
|
|
||||||
|
try {
|
||||||
|
value ? WiFiRemoteDebugger.start() : WiFiRemoteDebugger.stop();
|
||||||
|
} catch(e) {
|
||||||
|
dump("Error while initializing WiFi devtools: "
|
||||||
|
+ e + "\n" + e.stack + "\n");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
// =================== Device Storage ====================
|
// =================== Device Storage ====================
|
||||||
SettingsListener.observe('device.storage.writable.name', 'sdcard', function(value) {
|
SettingsListener.observe('device.storage.writable.name', 'sdcard', function(value) {
|
||||||
if (Services.prefs.getPrefType('device.storage.writable.name') != Ci.nsIPrefBranch.PREF_STRING) {
|
if (Services.prefs.getPrefType('device.storage.writable.name') != Ci.nsIPrefBranch.PREF_STRING) {
|
||||||
@ -657,6 +690,9 @@ let settingsToObserve = {
|
|||||||
defaultValue: false
|
defaultValue: false
|
||||||
},
|
},
|
||||||
'devtools.eventlooplag.threshold': 100,
|
'devtools.eventlooplag.threshold': 100,
|
||||||
|
'devtools.remote.wifi.visible': {
|
||||||
|
resetToPref: true
|
||||||
|
},
|
||||||
'dom.mozApps.use_reviewer_certs': false,
|
'dom.mozApps.use_reviewer_certs': false,
|
||||||
'layers.draw-borders': false,
|
'layers.draw-borders': false,
|
||||||
'layers.draw-tile-borders': false,
|
'layers.draw-tile-borders': false,
|
||||||
|
@ -56,6 +56,16 @@ XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
|
|||||||
return DebuggerServer;
|
return DebuggerServer;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, 'devtools', function() {
|
||||||
|
const { devtools } =
|
||||||
|
Cu.import('resource://gre/modules/devtools/Loader.jsm', {});
|
||||||
|
return devtools;
|
||||||
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(this, 'discovery', function() {
|
||||||
|
return devtools.require('devtools/toolkit/discovery/discovery');
|
||||||
|
});
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
||||||
return Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
return Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||||
.getService(Ci.nsIMessageListenerManager);
|
.getService(Ci.nsIMessageListenerManager);
|
||||||
@ -809,7 +819,6 @@ let IndexedDBPromptHelper = {
|
|||||||
let RemoteDebugger = {
|
let RemoteDebugger = {
|
||||||
_promptDone: false,
|
_promptDone: false,
|
||||||
_promptAnswer: false,
|
_promptAnswer: false,
|
||||||
_running: false,
|
|
||||||
|
|
||||||
prompt: function debugger_prompt() {
|
prompt: function debugger_prompt() {
|
||||||
this._promptDone = false;
|
this._promptDone = false;
|
||||||
@ -830,22 +839,11 @@ let RemoteDebugger = {
|
|||||||
this._promptDone = true;
|
this._promptDone = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
get isDebugging() {
|
initServer: function() {
|
||||||
if (!this._running) {
|
if (DebuggerServer.initialized) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DebuggerServer._connections &&
|
|
||||||
Object.keys(DebuggerServer._connections).length > 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Start the debugger server.
|
|
||||||
start: function debugger_start() {
|
|
||||||
if (this._running) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DebuggerServer.initialized) {
|
|
||||||
// Ask for remote connections.
|
// Ask for remote connections.
|
||||||
DebuggerServer.init(this.prompt.bind(this));
|
DebuggerServer.init(this.prompt.bind(this));
|
||||||
|
|
||||||
@ -886,7 +884,6 @@ let RemoteDebugger = {
|
|||||||
deviceActor: DebuggerServer.globalActorFactories.deviceActor,
|
deviceActor: DebuggerServer.globalActorFactories.deviceActor,
|
||||||
} : DebuggerServer.globalActorFactories
|
} : DebuggerServer.globalActorFactories
|
||||||
};
|
};
|
||||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
|
||||||
let { RootActor } = devtools.require("devtools/server/actors/root");
|
let { RootActor } = devtools.require("devtools/server/actors/root");
|
||||||
let root = new RootActor(connection, parameters);
|
let root = new RootActor(connection, parameters);
|
||||||
root.applicationType = "operating-system";
|
root.applicationType = "operating-system";
|
||||||
@ -899,40 +896,92 @@ let RemoteDebugger = {
|
|||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let path = Services.prefs.getCharPref("devtools.debugger.unix-domain-socket") ||
|
let USBRemoteDebugger = {
|
||||||
|
|
||||||
|
get isDebugging() {
|
||||||
|
if (!this._listener) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DebuggerServer._connections &&
|
||||||
|
Object.keys(DebuggerServer._connections).length > 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
start: function() {
|
||||||
|
if (this._listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteDebugger.initServer();
|
||||||
|
|
||||||
|
let portOrPath =
|
||||||
|
Services.prefs.getCharPref("devtools.debugger.unix-domain-socket") ||
|
||||||
"/data/local/debugger-socket";
|
"/data/local/debugger-socket";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DebuggerServer.openListener(path);
|
debug("Starting USB debugger on " + portOrPath);
|
||||||
|
this._listener = DebuggerServer.openListener(portOrPath);
|
||||||
// Temporary event, until bug 942756 lands and offers a way to know
|
// Temporary event, until bug 942756 lands and offers a way to know
|
||||||
// when the server is up and running.
|
// when the server is up and running.
|
||||||
Services.obs.notifyObservers(null, 'debugger-server-started', null);
|
Services.obs.notifyObservers(null, 'debugger-server-started', null);
|
||||||
this._running = true;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dump('Unable to start debugger server: ' + e + '\n');
|
debug('Unable to start USB debugger server: ' + e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
stop: function debugger_stop() {
|
stop: function() {
|
||||||
if (!this._running) {
|
if (!this._listener) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DebuggerServer.initialized) {
|
|
||||||
// Can this really happen if we are running?
|
|
||||||
this._running = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
DebuggerServer.closeAllListeners();
|
this._listener.close();
|
||||||
|
this._listener = null;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dump('Unable to stop debugger server: ' + e + '\n');
|
debug('Unable to stop USB debugger server: ' + e);
|
||||||
}
|
|
||||||
this._running = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
let WiFiRemoteDebugger = {
|
||||||
|
|
||||||
|
start: function() {
|
||||||
|
if (this._listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteDebugger.initServer();
|
||||||
|
|
||||||
|
try {
|
||||||
|
debug("Starting WiFi debugger");
|
||||||
|
this._listener = DebuggerServer.openListener(-1);
|
||||||
|
let port = this._listener.port;
|
||||||
|
debug("Started WiFi debugger on " + port);
|
||||||
|
discovery.addService("devtools", { port: port });
|
||||||
|
} catch (e) {
|
||||||
|
debug('Unable to start WiFi debugger server: ' + e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function() {
|
||||||
|
if (!this._listener) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
discovery.removeService("devtools");
|
||||||
|
this._listener.close();
|
||||||
|
this._listener = null;
|
||||||
|
} catch (e) {
|
||||||
|
debug('Unable to stop WiFi debugger server: ' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
let KeyboardHelper = {
|
let KeyboardHelper = {
|
||||||
handleEvent: function keyboard_handleEvent(detail) {
|
handleEvent: function keyboard_handleEvent(detail) {
|
||||||
Keyboard.setLayouts(detail.layouts);
|
Keyboard.setLayouts(detail.layouts);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
|
<project name="platform_build" path="build" remote="b2g" revision="999e945b85c578c503ad445c2285940f16aacdae">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
|
@ -4,6 +4,6 @@
|
|||||||
"remote": "",
|
"remote": "",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "18f160082057a1c10754458f9e4944220099ab67",
|
"revision": "eff18c4265f0d8e49e5a2f2d7c9fdb01c87bd42e",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="dc5ca96695cab87b4c2fcd7c9f046ae3415a70a5"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="31215645c296ba7a62bcb3176f69e0014ab9be07"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="cd50cb6ddeb430ddaf43e4fcf5774b9d262a8cf3"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="78cbbaeb041e5dd25a32c521b3d4ff08735ac139"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7f792d756385bb894fba7645da59c67fe2c804bf"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
@ -207,8 +207,8 @@ let SnapshotsListView = Heritage.extend(WidgetMethods, {
|
|||||||
|
|
||||||
let thumbnail = document.createElementNS(HTML_NS, "canvas");
|
let thumbnail = document.createElementNS(HTML_NS, "canvas");
|
||||||
thumbnail.className = "snapshot-item-thumbnail";
|
thumbnail.className = "snapshot-item-thumbnail";
|
||||||
thumbnail.width = CanvasFront.THUMBNAIL_HEIGHT;
|
thumbnail.width = CanvasFront.THUMBNAIL_SIZE;
|
||||||
thumbnail.height = CanvasFront.THUMBNAIL_HEIGHT;
|
thumbnail.height = CanvasFront.THUMBNAIL_SIZE;
|
||||||
|
|
||||||
let title = document.createElement("label");
|
let title = document.createElement("label");
|
||||||
title.className = "plain snapshot-item-title";
|
title.className = "plain snapshot-item-title";
|
||||||
@ -712,14 +712,16 @@ let CallsListView = Heritage.extend(WidgetMethods, {
|
|||||||
* A single "snapshot-image" instance received from the backend.
|
* A single "snapshot-image" instance received from the backend.
|
||||||
*/
|
*/
|
||||||
showScreenshot: function(screenshot) {
|
showScreenshot: function(screenshot) {
|
||||||
let { index, width, height, flipped, pixels } = screenshot;
|
let { index, width, height, scaling, flipped, pixels } = screenshot;
|
||||||
|
|
||||||
let screenshotNode = $("#screenshot-image");
|
let screenshotNode = $("#screenshot-image");
|
||||||
screenshotNode.setAttribute("flipped", flipped);
|
screenshotNode.setAttribute("flipped", flipped);
|
||||||
drawBackground("screenshot-rendering", width, height, pixels);
|
drawBackground("screenshot-rendering", width, height, pixels);
|
||||||
|
|
||||||
let dimensionsNode = $("#screenshot-dimensions");
|
let dimensionsNode = $("#screenshot-dimensions");
|
||||||
dimensionsNode.setAttribute("value", ~~width + " x " + ~~height);
|
let actualWidth = (width / scaling) | 0;
|
||||||
|
let actualHeight = (height / scaling) | 0;
|
||||||
|
dimensionsNode.setAttribute("value", actualWidth + " x " + actualHeight);
|
||||||
|
|
||||||
window.emit(EVENTS.CALL_SCREENSHOT_DISPLAYED);
|
window.emit(EVENTS.CALL_SCREENSHOT_DISPLAYED);
|
||||||
},
|
},
|
||||||
@ -754,8 +756,8 @@ let CallsListView = Heritage.extend(WidgetMethods, {
|
|||||||
|
|
||||||
let thumbnailNode = document.createElementNS(HTML_NS, "canvas");
|
let thumbnailNode = document.createElementNS(HTML_NS, "canvas");
|
||||||
thumbnailNode.setAttribute("flipped", flipped);
|
thumbnailNode.setAttribute("flipped", flipped);
|
||||||
thumbnailNode.width = Math.max(CanvasFront.THUMBNAIL_HEIGHT, width);
|
thumbnailNode.width = Math.max(CanvasFront.THUMBNAIL_SIZE, width);
|
||||||
thumbnailNode.height = Math.max(CanvasFront.THUMBNAIL_HEIGHT, height);
|
thumbnailNode.height = Math.max(CanvasFront.THUMBNAIL_SIZE, height);
|
||||||
drawImage(thumbnailNode, width, height, pixels, { centered: true });
|
drawImage(thumbnailNode, width, height, pixels, { centered: true });
|
||||||
|
|
||||||
thumbnailNode.className = "filmstrip-thumbnail";
|
thumbnailNode.className = "filmstrip-thumbnail";
|
||||||
|
@ -5,6 +5,7 @@ support-files =
|
|||||||
doc_simple-canvas-bitmasks.html
|
doc_simple-canvas-bitmasks.html
|
||||||
doc_simple-canvas-deep-stack.html
|
doc_simple-canvas-deep-stack.html
|
||||||
doc_simple-canvas-transparent.html
|
doc_simple-canvas-transparent.html
|
||||||
|
doc_webgl-bindings.html
|
||||||
doc_webgl-enum.html
|
doc_webgl-enum.html
|
||||||
head.js
|
head.js
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ support-files =
|
|||||||
[browser_canvas-actor-test-07.js]
|
[browser_canvas-actor-test-07.js]
|
||||||
[browser_canvas-actor-test-08.js]
|
[browser_canvas-actor-test-08.js]
|
||||||
[browser_canvas-actor-test-09.js]
|
[browser_canvas-actor-test-09.js]
|
||||||
|
[browser_canvas-actor-test-10.js]
|
||||||
[browser_canvas-frontend-call-highlight.js]
|
[browser_canvas-frontend-call-highlight.js]
|
||||||
[browser_canvas-frontend-call-list.js]
|
[browser_canvas-frontend-call-list.js]
|
||||||
[browser_canvas-frontend-call-search.js]
|
[browser_canvas-frontend-call-search.js]
|
||||||
|
@ -18,9 +18,7 @@ function ifTestingSupported() {
|
|||||||
ok(true, "Target automatically navigated when the front was set up.");
|
ok(true, "Target automatically navigated when the front was set up.");
|
||||||
|
|
||||||
let snapshotActor = yield front.recordAnimationFrame();
|
let snapshotActor = yield front.recordAnimationFrame();
|
||||||
|
|
||||||
let animationOverview = yield snapshotActor.getOverview();
|
let animationOverview = yield snapshotActor.getOverview();
|
||||||
|
|
||||||
let functionCalls = animationOverview.calls;
|
let functionCalls = animationOverview.calls;
|
||||||
|
|
||||||
is(functionCalls[0].name, "clearRect",
|
is(functionCalls[0].name, "clearRect",
|
||||||
|
@ -26,6 +26,11 @@ function ifTestingSupported() {
|
|||||||
is(functionCalls[0].argsPreview, "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT | COLOR_BUFFER_BIT",
|
is(functionCalls[0].argsPreview, "DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT | COLOR_BUFFER_BIT",
|
||||||
"The bits passed into `gl.clear` have been cast to their enum values.");
|
"The bits passed into `gl.clear` have been cast to their enum values.");
|
||||||
|
|
||||||
|
is(functionCalls[1].name, "bindTexture",
|
||||||
|
"The function's name is correct.");
|
||||||
|
is(functionCalls[1].argsPreview, "TEXTURE_2D, null",
|
||||||
|
"The bits passed into `gl.bindTexture` have been cast to their enum values.");
|
||||||
|
|
||||||
yield removeTab(target.tab);
|
yield removeTab(target.tab);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the correct framebuffer, renderbuffer and textures are re-bound
|
||||||
|
* after generating screenshots using the actor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function ifTestingSupported() {
|
||||||
|
let [target, debuggee, front] = yield initCanavsDebuggerBackend(WEBGL_BINDINGS_URL);
|
||||||
|
|
||||||
|
let navigated = once(target, "navigate");
|
||||||
|
|
||||||
|
yield front.setup({ reload: true });
|
||||||
|
ok(true, "The front was setup up successfully.");
|
||||||
|
|
||||||
|
yield navigated;
|
||||||
|
ok(true, "Target automatically navigated when the front was set up.");
|
||||||
|
|
||||||
|
let snapshotActor = yield front.recordAnimationFrame();
|
||||||
|
let animationOverview = yield snapshotActor.getOverview();
|
||||||
|
let functionCalls = animationOverview.calls;
|
||||||
|
|
||||||
|
let firstScreenshot = yield snapshotActor.generateScreenshotFor(functionCalls[0]);
|
||||||
|
is(firstScreenshot.index, -1,
|
||||||
|
"The first screenshot didn't encounter any draw call.");
|
||||||
|
is(firstScreenshot.scaling, 0.25,
|
||||||
|
"The first screenshot has the correct scaling.");
|
||||||
|
is(firstScreenshot.width, CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT,
|
||||||
|
"The first screenshot has the correct width.");
|
||||||
|
is(firstScreenshot.height, CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT,
|
||||||
|
"The first screenshot has the correct height.");
|
||||||
|
is(firstScreenshot.flipped, true,
|
||||||
|
"The first screenshot has the correct 'flipped' flag.");
|
||||||
|
is(firstScreenshot.pixels.length, 0,
|
||||||
|
"The first screenshot should be empty.");
|
||||||
|
|
||||||
|
let gl = debuggee.gl;
|
||||||
|
is(gl.getParameter(gl.FRAMEBUFFER_BINDING), debuggee.customFramebuffer,
|
||||||
|
"The debuggee's gl context framebuffer wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.RENDERBUFFER_BINDING), debuggee.customRenderbuffer,
|
||||||
|
"The debuggee's gl context renderbuffer wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.TEXTURE_BINDING_2D), debuggee.customTexture,
|
||||||
|
"The debuggee's gl context texture binding wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[0], 128,
|
||||||
|
"The debuggee's gl context viewport's left coord. wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[1], 256,
|
||||||
|
"The debuggee's gl context viewport's left coord. wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[2], 384,
|
||||||
|
"The debuggee's gl context viewport's left coord. wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[3], 512,
|
||||||
|
"The debuggee's gl context viewport's left coord. wasn't changed.");
|
||||||
|
|
||||||
|
let secondScreenshot = yield snapshotActor.generateScreenshotFor(functionCalls[1]);
|
||||||
|
is(secondScreenshot.index, 1,
|
||||||
|
"The second screenshot has the correct index.");
|
||||||
|
is(secondScreenshot.width, CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT,
|
||||||
|
"The second screenshot has the correct width.");
|
||||||
|
is(secondScreenshot.height, CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT,
|
||||||
|
"The second screenshot has the correct height.");
|
||||||
|
is(secondScreenshot.scaling, 0.25,
|
||||||
|
"The second screenshot has the correct scaling.");
|
||||||
|
is(secondScreenshot.flipped, true,
|
||||||
|
"The second screenshot has the correct 'flipped' flag.");
|
||||||
|
is(secondScreenshot.pixels.length, Math.pow(CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT, 2),
|
||||||
|
"The second screenshot should not be empty.");
|
||||||
|
is(new Uint8Array(secondScreenshot.pixels.buffer)[0], 0,
|
||||||
|
"The second screenshot has the correct red component.");
|
||||||
|
is(new Uint8Array(secondScreenshot.pixels.buffer)[1], 0,
|
||||||
|
"The second screenshot has the correct green component.");
|
||||||
|
is(new Uint8Array(secondScreenshot.pixels.buffer)[2], 255,
|
||||||
|
"The second screenshot has the correct blue component.");
|
||||||
|
is(new Uint8Array(secondScreenshot.pixels.buffer)[3], 255,
|
||||||
|
"The second screenshot has the correct alpha component.");
|
||||||
|
|
||||||
|
let gl = debuggee.gl;
|
||||||
|
is(gl.getParameter(gl.FRAMEBUFFER_BINDING), debuggee.customFramebuffer,
|
||||||
|
"The debuggee's gl context framebuffer still wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.RENDERBUFFER_BINDING), debuggee.customRenderbuffer,
|
||||||
|
"The debuggee's gl context renderbuffer still wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.TEXTURE_BINDING_2D), debuggee.customTexture,
|
||||||
|
"The debuggee's gl context texture binding still wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[0], 128,
|
||||||
|
"The debuggee's gl context viewport's left coord. still wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[1], 256,
|
||||||
|
"The debuggee's gl context viewport's left coord. still wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[2], 384,
|
||||||
|
"The debuggee's gl context viewport's left coord. still wasn't changed.");
|
||||||
|
is(gl.getParameter(gl.VIEWPORT)[3], 512,
|
||||||
|
"The debuggee's gl context viewport's left coord. still wasn't changed.");
|
||||||
|
|
||||||
|
yield removeTab(target.tab);
|
||||||
|
finish();
|
||||||
|
}
|
61
browser/devtools/canvasdebugger/test/doc_webgl-bindings.html
Normal file
61
browser/devtools/canvasdebugger/test/doc_webgl-bindings.html
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<!-- 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>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<canvas id="canvas" width="1024" height="1024"></canvas>
|
||||||
|
|
||||||
|
<script type="text/javascript;version=1.8">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let canvas, gl;
|
||||||
|
let customFramebuffer;
|
||||||
|
let customRenderbuffer;
|
||||||
|
let customTexture;
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
canvas = document.querySelector("canvas");
|
||||||
|
gl = canvas.getContext("webgl", { preserveDrawingBuffer: true });
|
||||||
|
gl.clearColor(1.0, 0.0, 0.0, 1.0);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
customFramebuffer = gl.createFramebuffer();
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, customFramebuffer);
|
||||||
|
|
||||||
|
customRenderbuffer = gl.createRenderbuffer();
|
||||||
|
gl.bindRenderbuffer(gl.RENDERBUFFER, customRenderbuffer);
|
||||||
|
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1024, 1024);
|
||||||
|
|
||||||
|
customTexture = gl.createTexture();
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, customTexture);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1024, 1024, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||||
|
|
||||||
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, customTexture, 0);
|
||||||
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, customRenderbuffer);
|
||||||
|
|
||||||
|
gl.viewport(128, 256, 384, 512);
|
||||||
|
gl.clearColor(0.0, 1.0, 0.0, 1.0);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
drawScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawScene() {
|
||||||
|
gl.clearColor(0.0, 0.0, 1.0, 1.0);
|
||||||
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||||
|
window.requestAnimationFrame(drawScene);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
function drawScene() {
|
function drawScene() {
|
||||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
|
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
|
||||||
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
||||||
window.requestAnimationFrame(drawScene);
|
window.requestAnimationFrame(drawScene);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -30,6 +30,7 @@ const SIMPLE_BITMASKS_URL = EXAMPLE_URL + "doc_simple-canvas-bitmasks.html";
|
|||||||
const SIMPLE_CANVAS_TRANSPARENT_URL = EXAMPLE_URL + "doc_simple-canvas-transparent.html";
|
const SIMPLE_CANVAS_TRANSPARENT_URL = EXAMPLE_URL + "doc_simple-canvas-transparent.html";
|
||||||
const SIMPLE_CANVAS_DEEP_STACK_URL = EXAMPLE_URL + "doc_simple-canvas-deep-stack.html";
|
const SIMPLE_CANVAS_DEEP_STACK_URL = EXAMPLE_URL + "doc_simple-canvas-deep-stack.html";
|
||||||
const WEBGL_ENUM_URL = EXAMPLE_URL + "doc_webgl-enum.html";
|
const WEBGL_ENUM_URL = EXAMPLE_URL + "doc_webgl-enum.html";
|
||||||
|
const WEBGL_BINDINGS_URL = EXAMPLE_URL + "doc_webgl-bindings.html";
|
||||||
|
|
||||||
// All tests are asynchronous.
|
// All tests are asynchronous.
|
||||||
waitForExplicitFinish();
|
waitForExplicitFinish();
|
||||||
|
@ -125,27 +125,29 @@ interface nsIPrincipal;
|
|||||||
*
|
*
|
||||||
* Parent process Child processes
|
* Parent process Child processes
|
||||||
* ---------------- -----------------
|
* ---------------- -----------------
|
||||||
* global PPMM
|
* global (GPPMM)
|
||||||
* |
|
* |
|
||||||
* +<----> child PPMM
|
* +-->parent in-process PIPMM<-->child in-process CIPPMM
|
||||||
* |
|
* |
|
||||||
* +-->parent PMM1<------------------>child process CMM1
|
* +-->parent (PPMM1)<------------------>child (CPMM1)
|
||||||
* |
|
* |
|
||||||
* +-->parent PMM2<------------------>child process PMM2
|
* +-->parent (PPMM2)<------------------>child (CPMM2)
|
||||||
* ...
|
* ...
|
||||||
*
|
*
|
||||||
* For example: the parent-process PMM1 sends messages directly to
|
* Note, PIPMM and CIPPMM both run in the parent process.
|
||||||
* only the child-process CMM1.
|
|
||||||
*
|
*
|
||||||
* For example: CMM1 sends messages directly to PMM1. The global PPMM
|
* For example: the parent-process PPMM1 sends messages to the
|
||||||
|
* child-process CPMM1.
|
||||||
|
*
|
||||||
|
* For example: CPMM1 sends messages directly to PPMM1. The global GPPMM
|
||||||
* will also notify their message listeners when the message arrives.
|
* will also notify their message listeners when the message arrives.
|
||||||
*
|
*
|
||||||
* For example: messages sent through the global PPMM will be
|
* For example: messages sent through the global GPPMM will be
|
||||||
* dispatched to the listeners of the same-process, "child PPMM".
|
* dispatched to the listeners of the same-process, CIPPMM, CPMM1,
|
||||||
* They will also be broadcast to PPM1, PPM2, etc.
|
* CPMM2, etc.
|
||||||
*
|
*
|
||||||
* ***** PERFORMANCE AND SECURITY WARNING *****
|
* ***** PERFORMANCE AND SECURITY WARNING *****
|
||||||
* Messages broadcast through the global PPMM can result in messages
|
* Messages broadcast through the GPPMM can result in messages
|
||||||
* being dispatched across many OS processes, and to many processes
|
* being dispatched across many OS processes, and to many processes
|
||||||
* with different permissions. Great care should be taken when
|
* with different permissions. Great care should be taken when
|
||||||
* broadcasting.
|
* broadcasting.
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
#include "mozilla/unused.h"
|
#include "mozilla/unused.h"
|
||||||
#include "mozilla/VisualEventTracer.h"
|
#include "mozilla/VisualEventTracer.h"
|
||||||
|
#include "URIUtils.h"
|
||||||
|
|
||||||
#ifdef MOZ_LOGGING
|
#ifdef MOZ_LOGGING
|
||||||
// so we can get logging even in release builds (but only for some things)
|
// so we can get logging even in release builds (but only for some things)
|
||||||
@ -4558,16 +4559,24 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI,
|
|||||||
|
|
||||||
// if this is a Strict-Transport-Security host and the cert
|
// if this is a Strict-Transport-Security host and the cert
|
||||||
// is bad, don't allow overrides (STS Spec section 7.3).
|
// is bad, don't allow overrides (STS Spec section 7.3).
|
||||||
|
uint32_t type = nsISiteSecurityService::HEADER_HSTS;
|
||||||
|
uint32_t flags = mInPrivateBrowsing
|
||||||
|
? nsISocketProvider::NO_PERMANENT_STORAGE
|
||||||
|
: 0;
|
||||||
|
bool isStsHost = false;
|
||||||
|
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||||
nsCOMPtr<nsISiteSecurityService> sss =
|
nsCOMPtr<nsISiteSecurityService> sss =
|
||||||
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
uint32_t flags =
|
rv = sss->IsSecureURI(type, aURI, flags, &isStsHost);
|
||||||
mInPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
|
|
||||||
|
|
||||||
bool isStsHost = false;
|
|
||||||
rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS,
|
|
||||||
aURI, flags, &isStsHost);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
} else {
|
||||||
|
mozilla::dom::ContentChild* cc =
|
||||||
|
mozilla::dom::ContentChild::GetSingleton();
|
||||||
|
mozilla::ipc::URIParams uri;
|
||||||
|
SerializeURI(aURI, uri);
|
||||||
|
cc->SendIsSecureURI(type, uri, flags, &isStsHost);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t bucketId;
|
uint32_t bucketId;
|
||||||
if (isStsHost) {
|
if (isStsHost) {
|
||||||
|
@ -884,7 +884,7 @@ WebappsApplicationMgmt.prototype = {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Webapps:Uninstall:Return:OK":
|
case "Webapps:Uninstall:Return:OK":
|
||||||
Services.DOMRequest.fireSuccess(req, msg.origin);
|
Services.DOMRequest.fireSuccess(req, msg.manifestURL);
|
||||||
break;
|
break;
|
||||||
case "Webapps:Uninstall:Return:KO":
|
case "Webapps:Uninstall:Return:KO":
|
||||||
Services.DOMRequest.fireError(req, "NOT_INSTALLED");
|
Services.DOMRequest.fireError(req, "NOT_INSTALLED");
|
||||||
|
@ -2080,14 +2080,11 @@ this.DOMApplicationRegistry = {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow multiple hosted apps installations from the same origin for now.
|
// Disallow reinstalls from the same manifest url for now.
|
||||||
// We will remove this code after multiple apps per origin are supported (bug 778277).
|
|
||||||
// This will also disallow reinstalls from the same origin for now.
|
|
||||||
for (let id in this.webapps) {
|
for (let id in this.webapps) {
|
||||||
if (this.webapps[id].origin == app.origin &&
|
if (this.webapps[id].manifestURL == app.manifestURL &&
|
||||||
!this.webapps[id].packageHash &&
|
|
||||||
this._isLaunchable(this.webapps[id])) {
|
this._isLaunchable(this.webapps[id])) {
|
||||||
sendError("MULTIPLE_APPS_PER_ORIGIN_FORBIDDEN");
|
sendError("REINSTALL_FORBIDDEN");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ support-files =
|
|||||||
|
|
||||||
[test_app_update.html]
|
[test_app_update.html]
|
||||||
[test_bug_795164.html]
|
[test_bug_795164.html]
|
||||||
|
[test_install_multiple_apps_origin.html]
|
||||||
[test_install_receipts.html]
|
[test_install_receipts.html]
|
||||||
[test_marketplace_pkg_install.html]
|
[test_marketplace_pkg_install.html]
|
||||||
skip-if = buildapp == "b2g" || toolkit == "android" # see bug 989806
|
skip-if = buildapp == "b2g" || toolkit == "android" # see bug 989806
|
||||||
|
112
dom/apps/tests/test_install_multiple_apps_origin.html
Normal file
112
dom/apps/tests/test_install_multiple_apps_origin.html
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id={778277}
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug {778277}</title>
|
||||||
|
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={778277}">Mozilla Bug {778277}</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script class="testbody" type="application/javascript;version=1.7">
|
||||||
|
|
||||||
|
var gManifestURL = "http://test/tests/dom/apps/tests/file_app.sjs?apptype=hosted&getmanifest=true";
|
||||||
|
var gGenerator = runTest();
|
||||||
|
|
||||||
|
function go() {
|
||||||
|
SpecialPowers.pushPermissions(
|
||||||
|
[{ "type": "webapps-manage", "allow": 1, "context": document }],
|
||||||
|
function() { gGenerator.next() });
|
||||||
|
}
|
||||||
|
|
||||||
|
function continueTest() {
|
||||||
|
try {
|
||||||
|
gGenerator.next();
|
||||||
|
} catch (e if e instanceof StopIteration) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish() {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function cbError(aEvent) {
|
||||||
|
ok(false, "Error callback invoked " +
|
||||||
|
aEvent.target.error.name + " " + aEvent.target.error.message);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install 2 apps from the same origin and uninstall them.
|
||||||
|
*/
|
||||||
|
function runTest() {
|
||||||
|
SpecialPowers.setAllAppsLaunchable(true);
|
||||||
|
|
||||||
|
var manifestURL1 = gManifestURL + "&app=1";
|
||||||
|
var manifestURL2 = gManifestURL + "&app=2";
|
||||||
|
|
||||||
|
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
request = navigator.mozApps.mgmt.getAll();
|
||||||
|
request.onerror = cbError;
|
||||||
|
request.onsuccess = continueTest;
|
||||||
|
yield undefined;
|
||||||
|
var initialAppsCount = request.result.length;
|
||||||
|
info("Starting with " + initialAppsCount + " apps installed.");
|
||||||
|
|
||||||
|
var request = navigator.mozApps.install(manifestURL1, { });
|
||||||
|
request.onerror = cbError;
|
||||||
|
request.onsuccess = continueTest;
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
var app1 = request.result;
|
||||||
|
ok(app1, "App 1 is non-null");
|
||||||
|
is(app1.manifestURL, manifestURL1, "App 1 manifest url is correct.");
|
||||||
|
|
||||||
|
request = navigator.mozApps.install(manifestURL2, { });
|
||||||
|
request.onerror = cbError;
|
||||||
|
request.onsuccess = continueTest;
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
var app2 = request.result;
|
||||||
|
ok(app2, "App 2 is non-null");
|
||||||
|
is(app2.manifestURL, manifestURL2, "App 2 manifest url is correct.");
|
||||||
|
|
||||||
|
request = navigator.mozApps.mgmt.uninstall(app1);
|
||||||
|
request.onerror = cbError;
|
||||||
|
request.onsuccess = continueTest;
|
||||||
|
yield undefined;
|
||||||
|
is(request.result, manifestURL1, "App 1 uninstalled.");
|
||||||
|
|
||||||
|
request = navigator.mozApps.mgmt.uninstall(app2);
|
||||||
|
request.onerror = cbError;
|
||||||
|
request.onsuccess = continueTest;
|
||||||
|
yield undefined;
|
||||||
|
is(request.result, manifestURL2, "App 2 uninstalled.");
|
||||||
|
|
||||||
|
request = navigator.mozApps.mgmt.getAll();
|
||||||
|
request.onerror = cbError;
|
||||||
|
request.onsuccess = continueTest;
|
||||||
|
yield undefined;
|
||||||
|
is(request.result.length, initialAppsCount, "All apps are uninstalled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
addLoadEvent(go);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -98,6 +98,7 @@
|
|||||||
#include "nsIPresShell.h"
|
#include "nsIPresShell.h"
|
||||||
#include "nsIRemoteBlob.h"
|
#include "nsIRemoteBlob.h"
|
||||||
#include "nsIScriptError.h"
|
#include "nsIScriptError.h"
|
||||||
|
#include "nsISiteSecurityService.h"
|
||||||
#include "nsIStyleSheet.h"
|
#include "nsIStyleSheet.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsIURIFixup.h"
|
#include "nsIURIFixup.h"
|
||||||
@ -3239,6 +3240,23 @@ ContentParent::RecvGetSystemMemory(const uint64_t& aGetterId)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ContentParent::RecvIsSecureURI(const uint32_t& type,
|
||||||
|
const URIParams& uri,
|
||||||
|
const uint32_t& flags,
|
||||||
|
bool* isSecureURI)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsISiteSecurityService> sss(do_GetService(NS_SSSERVICE_CONTRACTID));
|
||||||
|
if (!sss) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIURI> ourURI = DeserializeURI(uri);
|
||||||
|
if (!ourURI) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nsresult rv = sss->IsSecureURI(type, ourURI, flags, isSecureURI);
|
||||||
|
return NS_SUCCEEDED(rv);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentParent::RecvLoadURIExternal(const URIParams& uri)
|
ContentParent::RecvLoadURIExternal(const URIParams& uri)
|
||||||
|
@ -422,6 +422,9 @@ private:
|
|||||||
virtual bool RecvGetRandomValues(const uint32_t& length,
|
virtual bool RecvGetRandomValues(const uint32_t& length,
|
||||||
InfallibleTArray<uint8_t>* randomValues) MOZ_OVERRIDE;
|
InfallibleTArray<uint8_t>* randomValues) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool RecvIsSecureURI(const uint32_t& type, const URIParams& uri,
|
||||||
|
const uint32_t& flags, bool* isSecureURI);
|
||||||
|
|
||||||
virtual bool DeallocPHalParent(PHalParent*) MOZ_OVERRIDE;
|
virtual bool DeallocPHalParent(PHalParent*) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor) MOZ_OVERRIDE;
|
virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor) MOZ_OVERRIDE;
|
||||||
|
@ -478,6 +478,9 @@ parent:
|
|||||||
|
|
||||||
async GetSystemMemory(uint64_t getterId);
|
async GetSystemMemory(uint64_t getterId);
|
||||||
|
|
||||||
|
sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags)
|
||||||
|
returns (bool isSecureURI);
|
||||||
|
|
||||||
PHal();
|
PHal();
|
||||||
|
|
||||||
PIndexedDB();
|
PIndexedDB();
|
||||||
|
@ -97,6 +97,8 @@ typedef Tuple3<NetdCommand*, CommandChain*, CommandCallback> QueueData;
|
|||||||
#define GET_CURRENT_CALLBACK (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
|
#define GET_CURRENT_CALLBACK (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].c)
|
||||||
#define GET_CURRENT_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
|
#define GET_CURRENT_COMMAND (gCommandQueue.IsEmpty() ? nullptr : gCommandQueue[0].a->mData)
|
||||||
|
|
||||||
|
#define CNT_OF_ARRAY(a) (sizeof(a) / sizeof(a[0]))
|
||||||
|
|
||||||
static NetworkUtils* gNetworkUtils;
|
static NetworkUtils* gNetworkUtils;
|
||||||
static nsTArray<QueueData> gCommandQueue;
|
static nsTArray<QueueData> gCommandQueue;
|
||||||
static CurrentCommand gCurrentCommand;
|
static CurrentCommand gCurrentCommand;
|
||||||
@ -1087,54 +1089,64 @@ NetworkUtils::~NetworkUtils()
|
|||||||
|
|
||||||
void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
|
void NetworkUtils::ExecuteCommand(NetworkParams aOptions)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
typedef bool (NetworkUtils::*CommandHandler)(NetworkParams&);
|
||||||
|
|
||||||
if (aOptions.mCmd.EqualsLiteral("removeNetworkRoute")) {
|
const static struct {
|
||||||
removeNetworkRoute(aOptions);
|
const char* mCommandName;
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("setDNS")) {
|
CommandHandler mCommandHandler;
|
||||||
setDNS(aOptions);
|
} COMMAND_HANDLER_TABLE[] = {
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("setDefaultRouteAndDNS")) {
|
|
||||||
setDefaultRouteAndDNS(aOptions);
|
// For command 'testCommand', BUILD_ENTRY(testCommand) will generate
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("removeDefaultRoute")) {
|
// {"testCommand", NetworkUtils::testCommand}
|
||||||
removeDefaultRoute(aOptions);
|
#define BUILD_ENTRY(c) {#c, &NetworkUtils::c}
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("addHostRoute")) {
|
|
||||||
addHostRoute(aOptions);
|
BUILD_ENTRY(removeNetworkRoute),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("removeHostRoute")) {
|
BUILD_ENTRY(setDNS),
|
||||||
removeHostRoute(aOptions);
|
BUILD_ENTRY(setDefaultRouteAndDNS),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("removeHostRoutes")) {
|
BUILD_ENTRY(removeDefaultRoute),
|
||||||
removeHostRoutes(aOptions);
|
BUILD_ENTRY(addHostRoute),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("addSecondaryRoute")) {
|
BUILD_ENTRY(removeHostRoute),
|
||||||
addSecondaryRoute(aOptions);
|
BUILD_ENTRY(removeHostRoutes),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("removeSecondaryRoute")) {
|
BUILD_ENTRY(addSecondaryRoute),
|
||||||
removeSecondaryRoute(aOptions);
|
BUILD_ENTRY(removeSecondaryRoute),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("getNetworkInterfaceStats")) {
|
BUILD_ENTRY(getNetworkInterfaceStats),
|
||||||
getNetworkInterfaceStats(aOptions);
|
BUILD_ENTRY(setNetworkInterfaceAlarm),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("setNetworkInterfaceAlarm")) {
|
BUILD_ENTRY(enableNetworkInterfaceAlarm),
|
||||||
setNetworkInterfaceAlarm(aOptions);
|
BUILD_ENTRY(disableNetworkInterfaceAlarm),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("enableNetworkInterfaceAlarm")) {
|
BUILD_ENTRY(setWifiOperationMode),
|
||||||
enableNetworkInterfaceAlarm(aOptions);
|
BUILD_ENTRY(setDhcpServer),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("disableNetworkInterfaceAlarm")) {
|
BUILD_ENTRY(setWifiTethering),
|
||||||
disableNetworkInterfaceAlarm(aOptions);
|
BUILD_ENTRY(setUSBTethering),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("setWifiOperationMode")) {
|
BUILD_ENTRY(enableUsbRndis),
|
||||||
setWifiOperationMode(aOptions);
|
BUILD_ENTRY(updateUpStream),
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("setDhcpServer")) {
|
|
||||||
setDhcpServer(aOptions);
|
#undef BUILD_ENTRY
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("setWifiTethering")) {
|
};
|
||||||
setWifiTethering(aOptions);
|
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("setUSBTethering")) {
|
// Loop until we find the command name which matches aOptions.mCmd.
|
||||||
setUSBTethering(aOptions);
|
CommandHandler handler = nullptr;
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("enableUsbRndis")) {
|
for (size_t i = 0; i < CNT_OF_ARRAY(COMMAND_HANDLER_TABLE); i++) {
|
||||||
enableUsbRndis(aOptions);
|
if (aOptions.mCmd.EqualsASCII(COMMAND_HANDLER_TABLE[i].mCommandName)) {
|
||||||
} else if (aOptions.mCmd.EqualsLiteral("updateUpStream")) {
|
handler = COMMAND_HANDLER_TABLE[i].mCommandHandler;
|
||||||
updateUpStream(aOptions);
|
break;
|
||||||
} else {
|
}
|
||||||
WARN("unknon message");
|
}
|
||||||
|
|
||||||
|
if (!handler) {
|
||||||
|
// Command not found in COMMAND_HANDLER_TABLE.
|
||||||
|
WARN("unknown message: %s", NS_ConvertUTF16toUTF8(aOptions.mCmd).get());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command matches! Dispatch to the handler.
|
||||||
|
(this->*handler)(aOptions);
|
||||||
|
|
||||||
if (!aOptions.mIsAsync) {
|
if (!aOptions.mIsAsync) {
|
||||||
|
// The requested command is synchronous, which implies the actual result
|
||||||
|
// from netd is not important to the client. So, just notify the
|
||||||
|
// registered callback.
|
||||||
NetworkResultOptions result;
|
NetworkResultOptions result;
|
||||||
result.mRet = ret;
|
result.mRet = true;
|
||||||
postMessage(aOptions, result);
|
postMessage(aOptions, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -730,7 +730,8 @@ TelephonyService.prototype = {
|
|||||||
serviceId: aClientId,
|
serviceId: aClientId,
|
||||||
emergency: aCall.isEmergency,
|
emergency: aCall.isEmergency,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
direction: aCall.isOutgoing ? "outgoing" : "incoming"
|
direction: aCall.isOutgoing ? "outgoing" : "incoming",
|
||||||
|
hangUpLocal: aCall.hangUpLocal
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this._cdmaCallWaitingNumber != null) {
|
if (this._cdmaCallWaitingNumber != null) {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package org.mozilla.gecko.db;
|
package org.mozilla.gecko.db;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.db.BrowserContract;
|
||||||
import org.mozilla.gecko.db.BrowserContract.SearchHistory;
|
import org.mozilla.gecko.db.BrowserContract.SearchHistory;
|
||||||
|
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
@ -110,10 +111,11 @@ public class SearchHistoryProvider extends SharedBrowserDatabaseProvider {
|
|||||||
@Override
|
@Override
|
||||||
public Cursor query(Uri uri, String[] projection, String selection,
|
public Cursor query(Uri uri, String[] projection, String selection,
|
||||||
String[] selectionArgs, String sortOrder) {
|
String[] selectionArgs, String sortOrder) {
|
||||||
String groupBy = null;
|
final String groupBy = null;
|
||||||
String having = null;
|
final String having = null;
|
||||||
|
final String limit = uri.getQueryParameter(BrowserContract.PARAM_LIMIT);
|
||||||
final Cursor cursor = getReadableDatabase(uri).query(SearchHistory.TABLE_NAME, projection,
|
final Cursor cursor = getReadableDatabase(uri).query(SearchHistory.TABLE_NAME, projection,
|
||||||
selection, selectionArgs, groupBy, having, sortOrder);
|
selection, selectionArgs, groupBy, having, sortOrder, limit);
|
||||||
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
cursor.setNotificationUri(getContext().getContentResolver(), uri);
|
||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,13 @@ import org.mozilla.gecko.db.SearchHistoryProvider;
|
|||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
public class testSearchHistoryProvider extends ContentProviderTest {
|
public class testSearchHistoryProvider extends ContentProviderTest {
|
||||||
|
|
||||||
// Translations of "United Kingdom" in several different languages
|
// Translations of "United Kingdom" in several different languages
|
||||||
private static final String[] testStrings = {"An Ríocht Aontaithe", // Irish
|
private static final String[] testStrings = {
|
||||||
|
"An Ríocht Aontaithe", // Irish
|
||||||
"Angli", // Albanian
|
"Angli", // Albanian
|
||||||
"Britanniarum Regnum", // Latin
|
"Britanniarum Regnum", // Latin
|
||||||
"Britio", // Esperanto
|
"Britio", // Esperanto
|
||||||
@ -95,6 +97,7 @@ public class testSearchHistoryProvider extends ContentProviderTest {
|
|||||||
mTests.add(new TestInsert());
|
mTests.add(new TestInsert());
|
||||||
mTests.add(new TestUnicodeQuery());
|
mTests.add(new TestUnicodeQuery());
|
||||||
mTests.add(new TestTimestamp());
|
mTests.add(new TestTimestamp());
|
||||||
|
mTests.add(new TestLimit());
|
||||||
mTests.add(new TestDelete());
|
mTests.add(new TestDelete());
|
||||||
mTests.add(new TestIncrement());
|
mTests.add(new TestIncrement());
|
||||||
}
|
}
|
||||||
@ -111,6 +114,80 @@ public class testSearchHistoryProvider extends ContentProviderTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that we can pass a LIMIT clause using a query parameter.
|
||||||
|
*/
|
||||||
|
private class TestLimit extends TestCase {
|
||||||
|
@Override
|
||||||
|
public void test() throws Exception {
|
||||||
|
ContentValues cv;
|
||||||
|
for (int i = 0; i < testStrings.length; i++) {
|
||||||
|
cv = new ContentValues();
|
||||||
|
cv.put(SearchHistory.QUERY, testStrings[i]);
|
||||||
|
mProvider.insert(SearchHistory.CONTENT_URI, cv);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int limit = 5;
|
||||||
|
|
||||||
|
// Test 1: Handle proper input.
|
||||||
|
|
||||||
|
Uri uri = SearchHistory.CONTENT_URI
|
||||||
|
.buildUpon()
|
||||||
|
.appendQueryParameter(BrowserContract.PARAM_LIMIT, String.valueOf(limit))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Cursor c = mProvider.query(uri, null, null, null, null);
|
||||||
|
try {
|
||||||
|
mAsserter.is(c.getCount(), limit,
|
||||||
|
String.format("Should have %d results", limit));
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 2: Empty input yields all results.
|
||||||
|
|
||||||
|
uri = SearchHistory.CONTENT_URI
|
||||||
|
.buildUpon()
|
||||||
|
.appendQueryParameter(BrowserContract.PARAM_LIMIT, "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
c = mProvider.query(uri, null, null, null, null);
|
||||||
|
try {
|
||||||
|
mAsserter.is(c.getCount(), testStrings.length, "Should have all results");
|
||||||
|
} finally {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 3: Illegal params.
|
||||||
|
|
||||||
|
String[] illegalParams = new String[] {"a", "-1"};
|
||||||
|
boolean success = true;
|
||||||
|
|
||||||
|
for (String param : illegalParams) {
|
||||||
|
success = true;
|
||||||
|
|
||||||
|
uri = SearchHistory.CONTENT_URI
|
||||||
|
.buildUpon()
|
||||||
|
.appendQueryParameter(BrowserContract.PARAM_LIMIT, param)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
c = mProvider.query(uri, null, null, null, null);
|
||||||
|
success = false;
|
||||||
|
} catch(IllegalArgumentException e) {
|
||||||
|
// noop.
|
||||||
|
} finally {
|
||||||
|
if (c != null) {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mAsserter.ok(success, "LIMIT", param + " should have been an invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that we can insert values into the DB, including unicode.
|
* Verify that we can insert values into the DB, including unicode.
|
||||||
*/
|
*/
|
||||||
|
@ -654,6 +654,10 @@ pref("devtools.dump.emit", false);
|
|||||||
pref("devtools.discovery.log", false);
|
pref("devtools.discovery.log", false);
|
||||||
// Disable scanning for DevTools devices via WiFi
|
// Disable scanning for DevTools devices via WiFi
|
||||||
pref("devtools.remote.wifi.scan", false);
|
pref("devtools.remote.wifi.scan", false);
|
||||||
|
// Hide UI options for controlling device visibility over WiFi
|
||||||
|
// N.B.: This does not set whether the device can be discovered via WiFi, only
|
||||||
|
// whether the UI control to make such a choice is shown to the user
|
||||||
|
pref("devtools.remote.wifi.visible", false);
|
||||||
|
|
||||||
// view source
|
// view source
|
||||||
pref("view_source.syntax_highlight", true);
|
pref("view_source.syntax_highlight", true);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
#include "nsSecurityHeaderParser.h"
|
#include "nsSecurityHeaderParser.h"
|
||||||
|
#include "nsXULAppAPI.h"
|
||||||
|
|
||||||
// A note about the preload list:
|
// A note about the preload list:
|
||||||
// When a site specifically disables sts by sending a header with
|
// When a site specifically disables sts by sending a header with
|
||||||
@ -87,6 +88,11 @@ NS_IMPL_ISUPPORTS(nsSiteSecurityService,
|
|||||||
nsresult
|
nsresult
|
||||||
nsSiteSecurityService::Init()
|
nsSiteSecurityService::Init()
|
||||||
{
|
{
|
||||||
|
// Child processes are not allowed direct access to this.
|
||||||
|
if (XRE_GetProcessType() != GeckoProcessType_Default) {
|
||||||
|
MOZ_CRASH("Child process: no direct access to nsSiteSecurityService");
|
||||||
|
}
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
mPermMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
mPermMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
|
||||||
|
@ -210,9 +210,12 @@ let FunctionCallActor = protocol.ActorClass({
|
|||||||
// XXX: All of this sucks. Make this smarter, so that the frontend
|
// XXX: All of this sucks. Make this smarter, so that the frontend
|
||||||
// can inspect each argument, be it object or primitive. Bug 978960.
|
// can inspect each argument, be it object or primitive. Bug 978960.
|
||||||
let serializeArgs = () => args.map((arg, i) => {
|
let serializeArgs = () => args.map((arg, i) => {
|
||||||
if (typeof arg == "undefined") {
|
if (arg === undefined) {
|
||||||
return "undefined";
|
return "undefined";
|
||||||
}
|
}
|
||||||
|
if (arg === null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
if (typeof arg == "function") {
|
if (typeof arg == "function") {
|
||||||
return "Function";
|
return "Function";
|
||||||
}
|
}
|
||||||
@ -631,7 +634,7 @@ CallWatcherFront.ENUM_METHODS[CallWatcherFront.CANVAS_WEBGL_CONTEXT] = {
|
|||||||
stencilOpSeparate: [0, 1, 2, 3],
|
stencilOpSeparate: [0, 1, 2, 3],
|
||||||
texImage2D: (args) => args.length > 6 ? [0, 2, 6, 7] : [0, 2, 3, 4],
|
texImage2D: (args) => args.length > 6 ? [0, 2, 6, 7] : [0, 2, 3, 4],
|
||||||
texParameterf: [0, 1],
|
texParameterf: [0, 1],
|
||||||
texParameteri: [0, 1],
|
texParameteri: [0, 1, 2],
|
||||||
texSubImage2D: (args) => args.length === 9 ? [0, 6, 7] : [0, 4, 5],
|
texSubImage2D: (args) => args.length === 9 ? [0, 6, 7] : [0, 4, 5],
|
||||||
vertexAttribPointer: [2]
|
vertexAttribPointer: [2]
|
||||||
};
|
};
|
||||||
@ -643,7 +646,7 @@ CallWatcherFront.ENUM_METHODS[CallWatcherFront.CANVAS_WEBGL_CONTEXT] = {
|
|||||||
* For example, when gl.clear(gl.COLOR_BUFFER_BIT) is called, the actual passed
|
* For example, when gl.clear(gl.COLOR_BUFFER_BIT) is called, the actual passed
|
||||||
* argument's value is 16384, which we want identified as "COLOR_BUFFER_BIT".
|
* argument's value is 16384, which we want identified as "COLOR_BUFFER_BIT".
|
||||||
*/
|
*/
|
||||||
var gEnumRegex = /^[A-Z_]+$/;
|
var gEnumRegex = /^[A-Z][A-Z0-9_]+$/;
|
||||||
var gEnumsLookupTable = {};
|
var gEnumsLookupTable = {};
|
||||||
|
|
||||||
// These values are returned from errors, or empty values,
|
// These values are returned from errors, or empty values,
|
||||||
|
@ -80,6 +80,7 @@ protocol.types.addDictType("snapshot-image", {
|
|||||||
index: "number",
|
index: "number",
|
||||||
width: "number",
|
width: "number",
|
||||||
height: "number",
|
height: "number",
|
||||||
|
scaling: "number",
|
||||||
flipped: "boolean",
|
flipped: "boolean",
|
||||||
pixels: "uint32-array"
|
pixels: "uint32-array"
|
||||||
});
|
});
|
||||||
@ -117,7 +118,7 @@ let FrameSnapshotActor = protocol.ActorClass({
|
|||||||
protocol.Actor.prototype.initialize.call(this, conn);
|
protocol.Actor.prototype.initialize.call(this, conn);
|
||||||
this._contentCanvas = canvas;
|
this._contentCanvas = canvas;
|
||||||
this._functionCalls = calls;
|
this._functionCalls = calls;
|
||||||
this._lastDrawCallScreenshot = screenshot;
|
this._animationFrameEndScreenshot = screenshot;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -127,7 +128,7 @@ let FrameSnapshotActor = protocol.ActorClass({
|
|||||||
return {
|
return {
|
||||||
calls: this._functionCalls,
|
calls: this._functionCalls,
|
||||||
thumbnails: this._functionCalls.map(e => e._thumbnail).filter(e => !!e),
|
thumbnails: this._functionCalls.map(e => e._thumbnail).filter(e => !!e),
|
||||||
screenshot: this._lastDrawCallScreenshot
|
screenshot: this._animationFrameEndScreenshot
|
||||||
};
|
};
|
||||||
}, {
|
}, {
|
||||||
response: { overview: RetVal("snapshot-overview") }
|
response: { overview: RetVal("snapshot-overview") }
|
||||||
@ -148,7 +149,7 @@ let FrameSnapshotActor = protocol.ActorClass({
|
|||||||
// To get a screenshot, replay all the steps necessary to render the frame,
|
// To get a screenshot, replay all the steps necessary to render the frame,
|
||||||
// by invoking the context calls up to and including the specified one.
|
// by invoking the context calls up to and including the specified one.
|
||||||
// This will be done in a custom framebuffer in case of a WebGL context.
|
// This will be done in a custom framebuffer in case of a WebGL context.
|
||||||
let { replayContext, lastDrawCallIndex } = ContextUtils.replayAnimationFrame({
|
let replayData = ContextUtils.replayAnimationFrame({
|
||||||
contextType: global,
|
contextType: global,
|
||||||
canvas: canvas,
|
canvas: canvas,
|
||||||
calls: calls,
|
calls: calls,
|
||||||
@ -156,24 +157,25 @@ let FrameSnapshotActor = protocol.ActorClass({
|
|||||||
last: index
|
last: index
|
||||||
});
|
});
|
||||||
|
|
||||||
// To keep things fast, generate an image that's relatively small.
|
let { replayContext, replayContextScaling, lastDrawCallIndex, doCleanup } = replayData;
|
||||||
let dimensions = Math.min(CanvasFront.SCREENSHOT_HEIGHT_MAX, canvas.height);
|
let [left, top, width, height] = replayData.replayViewport;
|
||||||
let screenshot;
|
let screenshot;
|
||||||
|
|
||||||
// Depending on the canvas' context, generating a screenshot is done
|
// Depending on the canvas' context, generating a screenshot is done
|
||||||
// in different ways. In case of the WebGL context, we also need to reset
|
// in different ways.
|
||||||
// the framebuffer binding to the default value.
|
|
||||||
if (global == CallWatcherFront.CANVAS_WEBGL_CONTEXT) {
|
if (global == CallWatcherFront.CANVAS_WEBGL_CONTEXT) {
|
||||||
screenshot = ContextUtils.getPixelsForWebGL(replayContext);
|
screenshot = ContextUtils.getPixelsForWebGL(replayContext, left, top, width, height);
|
||||||
replayContext.bindFramebuffer(replayContext.FRAMEBUFFER, null);
|
|
||||||
screenshot.flipped = true;
|
screenshot.flipped = true;
|
||||||
}
|
} else if (global == CallWatcherFront.CANVAS_2D_CONTEXT) {
|
||||||
// In case of 2D contexts, no additional special treatment is necessary.
|
screenshot = ContextUtils.getPixelsFor2D(replayContext, left, top, width, height);
|
||||||
else if (global == CallWatcherFront.CANVAS_2D_CONTEXT) {
|
|
||||||
screenshot = ContextUtils.getPixelsFor2D(replayContext);
|
|
||||||
screenshot.flipped = false;
|
screenshot.flipped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case of the WebGL context, we also need to reset the framebuffer
|
||||||
|
// binding to the original value, after generating the screenshot.
|
||||||
|
doCleanup();
|
||||||
|
|
||||||
|
screenshot.scaling = replayContextScaling;
|
||||||
screenshot.index = lastDrawCallIndex;
|
screenshot.index = lastDrawCallIndex;
|
||||||
return screenshot;
|
return screenshot;
|
||||||
}, {
|
}, {
|
||||||
@ -188,17 +190,17 @@ let FrameSnapshotActor = protocol.ActorClass({
|
|||||||
let FrameSnapshotFront = protocol.FrontClass(FrameSnapshotActor, {
|
let FrameSnapshotFront = protocol.FrontClass(FrameSnapshotActor, {
|
||||||
initialize: function(client, form) {
|
initialize: function(client, form) {
|
||||||
protocol.Front.prototype.initialize.call(this, client, form);
|
protocol.Front.prototype.initialize.call(this, client, form);
|
||||||
this._lastDrawCallScreenshot = null;
|
this._animationFrameEndScreenshot = null;
|
||||||
this._cachedScreenshots = new WeakMap();
|
this._cachedScreenshots = new WeakMap();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implementation caches the last draw call screenshot to optimize
|
* This implementation caches the animation frame end screenshot to optimize
|
||||||
* frontend requests to `generateScreenshotFor`.
|
* frontend requests to `generateScreenshotFor`.
|
||||||
*/
|
*/
|
||||||
getOverview: custom(function() {
|
getOverview: custom(function() {
|
||||||
return this._getOverview().then(data => {
|
return this._getOverview().then(data => {
|
||||||
this._lastDrawCallScreenshot = data.screenshot;
|
this._animationFrameEndScreenshot = data.screenshot;
|
||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
}, {
|
}, {
|
||||||
@ -211,7 +213,7 @@ let FrameSnapshotFront = protocol.FrontClass(FrameSnapshotActor, {
|
|||||||
*/
|
*/
|
||||||
generateScreenshotFor: custom(function(functionCall) {
|
generateScreenshotFor: custom(function(functionCall) {
|
||||||
if (CanvasFront.ANIMATION_GENERATORS.has(functionCall.name)) {
|
if (CanvasFront.ANIMATION_GENERATORS.has(functionCall.name)) {
|
||||||
return promise.resolve(this._lastDrawCallScreenshot);
|
return promise.resolve(this._animationFrameEndScreenshot);
|
||||||
}
|
}
|
||||||
let cachedScreenshot = this._cachedScreenshots.get(functionCall);
|
let cachedScreenshot = this._cachedScreenshots.get(functionCall);
|
||||||
if (cachedScreenshot) {
|
if (cachedScreenshot) {
|
||||||
@ -370,12 +372,13 @@ let CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||||||
let index = this._lastDrawCallIndex;
|
let index = this._lastDrawCallIndex;
|
||||||
let width = this._lastContentCanvasWidth;
|
let width = this._lastContentCanvasWidth;
|
||||||
let height = this._lastContentCanvasHeight;
|
let height = this._lastContentCanvasHeight;
|
||||||
let flipped = this._lastThumbnailFlipped;
|
let flipped = !!this._lastThumbnailFlipped; // undefined -> false
|
||||||
let pixels = ContextUtils.getPixelStorage()["32bit"];
|
let pixels = ContextUtils.getPixelStorage()["32bit"];
|
||||||
let lastDrawCallScreenshot = {
|
let animationFrameEndScreenshot = {
|
||||||
index: index,
|
index: index,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
|
scaling: 1,
|
||||||
flipped: flipped,
|
flipped: flipped,
|
||||||
pixels: pixels.subarray(0, width * height)
|
pixels: pixels.subarray(0, width * height)
|
||||||
};
|
};
|
||||||
@ -385,7 +388,7 @@ let CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||||||
let frameSnapshot = new FrameSnapshotActor(this.conn, {
|
let frameSnapshot = new FrameSnapshotActor(this.conn, {
|
||||||
canvas: this._lastDrawCallCanvas,
|
canvas: this._lastDrawCallCanvas,
|
||||||
calls: functionCalls,
|
calls: functionCalls,
|
||||||
screenshot: lastDrawCallScreenshot
|
screenshot: animationFrameEndScreenshot
|
||||||
});
|
});
|
||||||
|
|
||||||
this._currentAnimationFrameSnapshot.resolve(frameSnapshot);
|
this._currentAnimationFrameSnapshot.resolve(frameSnapshot);
|
||||||
@ -408,7 +411,7 @@ let CanvasActor = exports.CanvasActor = protocol.ActorClass({
|
|||||||
let h = this._lastContentCanvasHeight = contentCanvas.height;
|
let h = this._lastContentCanvasHeight = contentCanvas.height;
|
||||||
|
|
||||||
// To keep things fast, generate images of small and fixed dimensions.
|
// To keep things fast, generate images of small and fixed dimensions.
|
||||||
let dimensions = CanvasFront.THUMBNAIL_HEIGHT;
|
let dimensions = CanvasFront.THUMBNAIL_SIZE;
|
||||||
let thumbnail;
|
let thumbnail;
|
||||||
|
|
||||||
// Create a thumbnail on every draw call on the canvas context, to augment
|
// Create a thumbnail on every draw call on the canvas context, to augment
|
||||||
@ -529,7 +532,7 @@ let ContextUtils = {
|
|||||||
*/
|
*/
|
||||||
resizePixels: function(srcPixels, srcWidth, srcHeight, dstHeight) {
|
resizePixels: function(srcPixels, srcWidth, srcHeight, dstHeight) {
|
||||||
let screenshotRatio = dstHeight / srcHeight;
|
let screenshotRatio = dstHeight / srcHeight;
|
||||||
let dstWidth = Math.floor(srcWidth * screenshotRatio);
|
let dstWidth = (srcWidth * screenshotRatio) | 0;
|
||||||
|
|
||||||
// Use a plain array instead of a Uint32Array to make serializing faster.
|
// Use a plain array instead of a Uint32Array to make serializing faster.
|
||||||
let dstPixels = new Array(dstWidth * dstHeight);
|
let dstPixels = new Array(dstWidth * dstHeight);
|
||||||
@ -540,8 +543,8 @@ let ContextUtils = {
|
|||||||
|
|
||||||
for (let dstX = 0; dstX < dstWidth; dstX++) {
|
for (let dstX = 0; dstX < dstWidth; dstX++) {
|
||||||
for (let dstY = 0; dstY < dstHeight; dstY++) {
|
for (let dstY = 0; dstY < dstHeight; dstY++) {
|
||||||
let srcX = Math.floor(dstX / screenshotRatio);
|
let srcX = (dstX / screenshotRatio) | 0;
|
||||||
let srcY = Math.floor(dstY / screenshotRatio);
|
let srcY = (dstY / screenshotRatio) | 0;
|
||||||
let cPos = srcX + srcWidth * srcY;
|
let cPos = srcX + srcWidth * srcY;
|
||||||
let dPos = dstX + dstWidth * dstY;
|
let dPos = dstX + dstWidth * dstY;
|
||||||
let color = dstPixels[dPos] = srcPixels[cPos];
|
let color = dstPixels[dPos] = srcPixels[cPos];
|
||||||
@ -566,8 +569,11 @@ let ContextUtils = {
|
|||||||
* the respective canvas, and the rendering will be performed into it.
|
* the respective canvas, and the rendering will be performed into it.
|
||||||
* This is necessary because some state (like shaders, textures etc.) can't
|
* This is necessary because some state (like shaders, textures etc.) can't
|
||||||
* be shared between two different WebGL contexts.
|
* be shared between two different WebGL contexts.
|
||||||
* Hopefully, once SharedResources are a thing this won't be necessary:
|
* - Hopefully, once SharedResources are a thing this won't be necessary:
|
||||||
* http://www.khronos.org/webgl/wiki/SharedResouces
|
* http://www.khronos.org/webgl/wiki/SharedResouces
|
||||||
|
* - Alternatively, we could pursue the idea of using the same context
|
||||||
|
* for multiple canvases, instead of trying to share resources:
|
||||||
|
* https://www.khronos.org/webgl/public-mailing-list/archives/1210/msg00058.html
|
||||||
*
|
*
|
||||||
* In case of a 2D context, a new canvas is created, since there's no
|
* In case of a 2D context, a new canvas is created, since there's no
|
||||||
* intrinsic state that can't be easily duplicated.
|
* intrinsic state that can't be easily duplicated.
|
||||||
@ -583,33 +589,59 @@ let ContextUtils = {
|
|||||||
* @param number last
|
* @param number last
|
||||||
* The last (inclusive) function call to end at.
|
* The last (inclusive) function call to end at.
|
||||||
* @return object
|
* @return object
|
||||||
* The context on which the specified calls were invoked and the
|
* The context on which the specified calls were invoked, the
|
||||||
* last registered draw call's index.
|
* last registered draw call's index and a cleanup function, which
|
||||||
|
* needs to be called whenever any potential followup work is finished.
|
||||||
*/
|
*/
|
||||||
replayAnimationFrame: function({ contextType, canvas, calls, first, last }) {
|
replayAnimationFrame: function({ contextType, canvas, calls, first, last }) {
|
||||||
let w = canvas.width;
|
let w = canvas.width;
|
||||||
let h = canvas.height;
|
let h = canvas.height;
|
||||||
|
|
||||||
let replayCanvas;
|
|
||||||
let replayContext;
|
let replayContext;
|
||||||
|
let replayContextScaling;
|
||||||
|
let customViewport;
|
||||||
let customFramebuffer;
|
let customFramebuffer;
|
||||||
let lastDrawCallIndex = -1;
|
let lastDrawCallIndex = -1;
|
||||||
|
let doCleanup = () => {};
|
||||||
|
|
||||||
// In case of WebGL contexts, rendering will be done offscreen, in a
|
// In case of WebGL contexts, rendering will be done offscreen, in a
|
||||||
// custom framebuffer, but on the provided canvas context.
|
// custom framebuffer, but using the same provided context. This is
|
||||||
|
// necessary because it's very memory-unfriendly to rebuild all the
|
||||||
|
// required GL state (like recompiling shaders, setting global flags, etc.)
|
||||||
|
// in an entirely new canvas. However, special care is needed to not
|
||||||
|
// permanently affect the existing GL state in the process.
|
||||||
if (contextType == CallWatcherFront.CANVAS_WEBGL_CONTEXT) {
|
if (contextType == CallWatcherFront.CANVAS_WEBGL_CONTEXT) {
|
||||||
replayCanvas = canvas;
|
// To keep things fast, replay the context calls on a framebuffer
|
||||||
replayContext = this.getWebGLContext(replayCanvas);
|
// of smaller dimensions than the actual canvas (maximum 256x256 pixels).
|
||||||
customFramebuffer = this.createBoundFramebuffer(replayContext, w, h);
|
let scaling = Math.min(CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT, h) / h;
|
||||||
|
replayContextScaling = scaling;
|
||||||
|
w = (w * scaling) | 0;
|
||||||
|
h = (h * scaling) | 0;
|
||||||
|
|
||||||
|
// Fetch the same WebGL context and bind a new framebuffer.
|
||||||
|
let gl = replayContext = this.getWebGLContext(canvas);
|
||||||
|
let { newFramebuffer, oldFramebuffer } = this.createBoundFramebuffer(gl, w, h);
|
||||||
|
customFramebuffer = newFramebuffer;
|
||||||
|
|
||||||
|
// Set the viewport to match the new framebuffer's dimensions.
|
||||||
|
let { newViewport, oldViewport } = this.setCustomViewport(gl, w, h);
|
||||||
|
customViewport = newViewport;
|
||||||
|
|
||||||
|
// Revert the framebuffer and viewport to the original values.
|
||||||
|
doCleanup = () => {
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, oldFramebuffer);
|
||||||
|
gl.viewport.apply(gl, oldViewport);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
// In case of 2D contexts, draw everything on a separate canvas context.
|
// In case of 2D contexts, draw everything on a separate canvas context.
|
||||||
else if (contextType == CallWatcherFront.CANVAS_2D_CONTEXT) {
|
else if (contextType == CallWatcherFront.CANVAS_2D_CONTEXT) {
|
||||||
let contentDocument = canvas.ownerDocument;
|
let contentDocument = canvas.ownerDocument;
|
||||||
replayCanvas = contentDocument.createElement("canvas");
|
let replayCanvas = contentDocument.createElement("canvas");
|
||||||
replayCanvas.width = w;
|
replayCanvas.width = w;
|
||||||
replayCanvas.height = h;
|
replayCanvas.height = h;
|
||||||
replayContext = replayCanvas.getContext("2d");
|
replayContext = replayCanvas.getContext("2d");
|
||||||
replayContext.clearRect(0, 0, w, h);
|
replayContextScaling = 1;
|
||||||
|
customViewport = [0, 0, w, h];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replay all the context calls up to and including the specified one.
|
// Replay all the context calls up to and including the specified one.
|
||||||
@ -620,23 +652,33 @@ let ContextUtils = {
|
|||||||
// to the default value, since we want to perform the rendering offscreen.
|
// to the default value, since we want to perform the rendering offscreen.
|
||||||
if (name == "bindFramebuffer" && args[1] == null) {
|
if (name == "bindFramebuffer" && args[1] == null) {
|
||||||
replayContext.bindFramebuffer(replayContext.FRAMEBUFFER, customFramebuffer);
|
replayContext.bindFramebuffer(replayContext.FRAMEBUFFER, customFramebuffer);
|
||||||
} else {
|
continue;
|
||||||
|
}
|
||||||
|
// Also prevent WebGL context calls that try to change the viewport
|
||||||
|
// while our custom framebuffer is bound.
|
||||||
|
if (name == "viewport") {
|
||||||
|
let framebufferBinding = replayContext.getParameter(replayContext.FRAMEBUFFER_BINDING);
|
||||||
|
if (framebufferBinding == customFramebuffer) {
|
||||||
|
replayContext.viewport.apply(replayContext, customViewport);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (type == CallWatcherFront.METHOD_FUNCTION) {
|
if (type == CallWatcherFront.METHOD_FUNCTION) {
|
||||||
replayContext[name].apply(replayContext, args);
|
replayContext[name].apply(replayContext, args);
|
||||||
} else if (type == CallWatcherFront.SETTER_FUNCTION) {
|
} else if (type == CallWatcherFront.SETTER_FUNCTION) {
|
||||||
replayContext[name] = args;
|
replayContext[name] = args;
|
||||||
} else {
|
|
||||||
// Ignore getter calls.
|
|
||||||
}
|
}
|
||||||
if (CanvasFront.DRAW_CALLS.has(name)) {
|
if (CanvasFront.DRAW_CALLS.has(name)) {
|
||||||
lastDrawCallIndex = i;
|
lastDrawCallIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
replayContext: replayContext,
|
replayContext: replayContext,
|
||||||
lastDrawCallIndex: lastDrawCallIndex
|
replayContextScaling: replayContextScaling,
|
||||||
|
replayViewport: customViewport,
|
||||||
|
lastDrawCallIndex: lastDrawCallIndex,
|
||||||
|
doCleanup: doCleanup
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -691,16 +733,21 @@ let ContextUtils = {
|
|||||||
* The generated framebuffer object.
|
* The generated framebuffer object.
|
||||||
*/
|
*/
|
||||||
createBoundFramebuffer: function(gl, width, height) {
|
createBoundFramebuffer: function(gl, width, height) {
|
||||||
let framebuffer = gl.createFramebuffer();
|
let oldFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
|
||||||
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
|
let oldRenderbufferBinding = gl.getParameter(gl.RENDERBUFFER_BINDING);
|
||||||
|
let oldTextureBinding = gl.getParameter(gl.TEXTURE_BINDING_2D);
|
||||||
|
|
||||||
// Use a texture as the color rendebuffer attachment, since consumenrs of
|
let newFramebuffer = gl.createFramebuffer();
|
||||||
|
gl.bindFramebuffer(gl.FRAMEBUFFER, newFramebuffer);
|
||||||
|
|
||||||
|
// Use a texture as the color renderbuffer attachment, since consumers of
|
||||||
// this function will most likely want to read the rendered pixels back.
|
// this function will most likely want to read the rendered pixels back.
|
||||||
let colorBuffer = gl.createTexture();
|
let colorBuffer = gl.createTexture();
|
||||||
gl.bindTexture(gl.TEXTURE_2D, colorBuffer);
|
gl.bindTexture(gl.TEXTURE_2D, colorBuffer);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
||||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
||||||
gl.generateMipmap(gl.TEXTURE_2D);
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||||
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
|
||||||
|
|
||||||
let depthBuffer = gl.createRenderbuffer();
|
let depthBuffer = gl.createRenderbuffer();
|
||||||
@ -710,10 +757,24 @@ let ContextUtils = {
|
|||||||
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorBuffer, 0);
|
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorBuffer, 0);
|
||||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
|
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthBuffer);
|
||||||
|
|
||||||
gl.bindTexture(gl.TEXTURE_2D, null);
|
gl.bindTexture(gl.TEXTURE_2D, oldTextureBinding);
|
||||||
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
|
gl.bindRenderbuffer(gl.RENDERBUFFER, oldRenderbufferBinding);
|
||||||
|
|
||||||
return framebuffer;
|
return { oldFramebuffer, newFramebuffer };
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the viewport of the drawing buffer for a WebGL context.
|
||||||
|
* @param WebGLRenderingContext gl
|
||||||
|
* @param number width
|
||||||
|
* @param number height
|
||||||
|
*/
|
||||||
|
setCustomViewport: function(gl, width, height) {
|
||||||
|
let oldViewport = XPCNativeWrapper.unwrap(gl.getParameter(gl.VIEWPORT));
|
||||||
|
let newViewport = [0, 0, width, height];
|
||||||
|
gl.viewport.apply(gl, newViewport);
|
||||||
|
|
||||||
|
return { oldViewport, newViewport };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -734,8 +795,8 @@ CanvasFront.CANVAS_CONTEXTS = new Set(CANVAS_CONTEXTS);
|
|||||||
CanvasFront.ANIMATION_GENERATORS = new Set(ANIMATION_GENERATORS);
|
CanvasFront.ANIMATION_GENERATORS = new Set(ANIMATION_GENERATORS);
|
||||||
CanvasFront.DRAW_CALLS = new Set(DRAW_CALLS);
|
CanvasFront.DRAW_CALLS = new Set(DRAW_CALLS);
|
||||||
CanvasFront.INTERESTING_CALLS = new Set(INTERESTING_CALLS);
|
CanvasFront.INTERESTING_CALLS = new Set(INTERESTING_CALLS);
|
||||||
CanvasFront.THUMBNAIL_HEIGHT = 50; // px
|
CanvasFront.THUMBNAIL_SIZE = 50; // px
|
||||||
CanvasFront.SCREENSHOT_HEIGHT_MAX = 256; // px
|
CanvasFront.WEBGL_SCREENSHOT_MAX_HEIGHT = 256; // px
|
||||||
CanvasFront.INVALID_SNAPSHOT_IMAGE = {
|
CanvasFront.INVALID_SNAPSHOT_IMAGE = {
|
||||||
index: -1,
|
index: -1,
|
||||||
width: 0,
|
width: 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user