зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
b998c68cd4
|
@ -20,7 +20,7 @@ LIBS += \
|
|||
$(DEPTH)/widget/gonk/libdisplay/$(LIB_PREFIX)display.$(LIB_SUFFIX) \
|
||||
$(MOZ_ZLIB_LIBS) \
|
||||
$(NULL)
|
||||
ifeq ($(ANDROID_VERSION),$(findstring $(ANDROID_VERSION),17 18))
|
||||
ifeq ($(ANDROID_VERSION),$(findstring $(ANDROID_VERSION),17 18 19))
|
||||
LIBS += \
|
||||
-lgui \
|
||||
-lsuspend \
|
||||
|
|
|
@ -1110,6 +1110,9 @@ let RemoteDebugger = {
|
|||
"/data/local/debugger-socket";
|
||||
try {
|
||||
DebuggerServer.openListener(path);
|
||||
// Temporary event, until bug 942756 lands and offer a way to know
|
||||
// when the server is up and running
|
||||
Services.obs.notifyObservers(null, 'debugger-server-started', null);
|
||||
this._running = true;
|
||||
} catch (e) {
|
||||
dump('Unable to start debugger server: ' + e + '\n');
|
||||
|
|
|
@ -86,13 +86,15 @@ DirectoryProvider.prototype = {
|
|||
// getUpdateDir will set persistent to false since it may toggle between
|
||||
// /data/local/ and /mnt/sdcard based on free space and/or availability
|
||||
// of the sdcard.
|
||||
return this.getUpdateDir(persistent, UPDATES_DIR);
|
||||
// before download, check if free space is 2.1 times of update.mar
|
||||
return this.getUpdateDir(persistent, UPDATES_DIR, 2.1);
|
||||
}
|
||||
if (prop == XRE_OS_UPDATE_APPLY_TO_DIR) {
|
||||
// getUpdateDir will set persistent to false since it may toggle between
|
||||
// /data/local/ and /mnt/sdcard based on free space and/or availability
|
||||
// of the sdcard.
|
||||
return this.getUpdateDir(persistent, FOTA_DIR);
|
||||
// before apply, check if free space is 1.1 times of update.mar
|
||||
return this.getUpdateDir(persistent, FOTA_DIR, 1.1);
|
||||
}
|
||||
#else
|
||||
// In desktop builds, coreAppsDir is the same as the profile directory.
|
||||
|
@ -171,7 +173,7 @@ DirectoryProvider.prototype = {
|
|||
return null;
|
||||
},
|
||||
|
||||
getUpdateDir: function dp_getUpdateDir(persistent, subdir) {
|
||||
getUpdateDir: function dp_getUpdateDir(persistent, subdir, multiple) {
|
||||
let defaultUpdateDir = this.getDefaultUpdateDir();
|
||||
persistent.value = false;
|
||||
|
||||
|
@ -189,7 +191,7 @@ DirectoryProvider.prototype = {
|
|||
return defaultUpdateDir;
|
||||
}
|
||||
|
||||
let requiredSpace = selectedPatch.size * 2;
|
||||
let requiredSpace = selectedPatch.size * multiple;
|
||||
let updateDir = this.findUpdateDirWithFreeSpace(requiredSpace, subdir);
|
||||
if (updateDir) {
|
||||
return updateDir;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"revision": "458c7c1031a8ee2666b8b4c62301bacd74833332",
|
||||
"revision": "449764bc60bafa78cec7aa6cad0d65e558ab7473",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -4631,6 +4631,7 @@
|
|||
role="presentation"
|
||||
layer="true" />
|
||||
<xul:image xbl:inherits="src=image,fadein,pinned,selected"
|
||||
anonid="tab-icon-image"
|
||||
class="tab-icon-image"
|
||||
validate="never"
|
||||
role="presentation"/>
|
||||
|
|
|
@ -52,7 +52,7 @@ add_task(function() {
|
|||
ok(!navbar.hasAttribute("overflowing"), "Should start with a non-overflowing toolbar.");
|
||||
ok(CustomizableUI.inDefaultState, "Should start in default state.");
|
||||
|
||||
window.resizeTo(480, window.outerHeight);
|
||||
window.resizeTo(390, window.outerHeight);
|
||||
yield waitForCondition(() => navbar.hasAttribute("overflowing"));
|
||||
ok(!navbar.querySelector("#search-container"), "Search container should be overflowing");
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<overlay id="editBookmarkOverlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<vbox id="editBookmarkPanelContent">
|
||||
<vbox id="editBookmarkPanelContent" flex="1">
|
||||
<broadcaster id="paneElementsBroadcaster"/>
|
||||
|
||||
<hbox id="editBMPanel_selectionCount" hidden="true" pack="center">
|
||||
|
@ -107,13 +107,15 @@
|
|||
</hbox>
|
||||
</row>
|
||||
|
||||
<row align="center" id="editBMPanel_folderTreeRow" collapsed="true">
|
||||
<row id="editBMPanel_folderTreeRow" collapsed="true" flex="1">
|
||||
<spacer/>
|
||||
<vbox flex="1">
|
||||
<tree id="editBMPanel_folderTree"
|
||||
flex="1"
|
||||
class="placesTree"
|
||||
type="places"
|
||||
height="150"
|
||||
minheight="150"
|
||||
editable="true"
|
||||
onselect="gEditItemOverlay.onFolderTreeSelect();"
|
||||
hidecolumnpicker="true"
|
||||
|
|
|
@ -56,8 +56,10 @@ BrowserToolboxProcess.prototype = {
|
|||
// Create a separate loader instance, so that we can be sure to receive a
|
||||
// separate instance of the DebuggingServer from the rest of the devtools.
|
||||
// This allows us to safely use the tools against even the actors and
|
||||
// DebuggingServer itself.
|
||||
// DebuggingServer itself, especially since we can mark this loader as
|
||||
// invisible to the debugger (unlike the usual loader settings).
|
||||
this.loader = new DevToolsLoader();
|
||||
this.loader.invisibleToDebugger = true;
|
||||
this.loader.main("devtools/server/main");
|
||||
this.debuggerServer = this.loader.DebuggerServer;
|
||||
dumpn("Created a separate loader instance for the DebuggerServer.");
|
||||
|
|
|
@ -1268,9 +1268,6 @@ function MarkupContainer(aMarkupView, aNode, aInspector) {
|
|||
this._onMouseDown = this._onMouseDown.bind(this);
|
||||
this.elt.addEventListener("mousedown", this._onMouseDown, false);
|
||||
|
||||
this._onClick = this._onClick.bind(this);
|
||||
this.elt.addEventListener("click", this._onClick, false);
|
||||
|
||||
// Prepare the image preview tooltip data if any
|
||||
this._prepareImagePreview();
|
||||
}
|
||||
|
@ -1394,16 +1391,9 @@ MarkupContainer.prototype = {
|
|||
},
|
||||
|
||||
_onMouseDown: function(event) {
|
||||
if (event.target.nodeName !== "a") {
|
||||
this.hovered = false;
|
||||
this.markup.navigate(this);
|
||||
event.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
_onClick: function(event) {
|
||||
let target = event.target;
|
||||
|
||||
// Target may be a resource link (generated by the output-parser)
|
||||
if (target.nodeName === "a") {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
@ -1411,6 +1401,13 @@ MarkupContainer.prototype = {
|
|||
.tab.ownerDocument.defaultView;
|
||||
browserWin.openUILinkIn(target.href, "tab");
|
||||
}
|
||||
// Or it may be the "show more nodes" button (which already has its onclick)
|
||||
// Else, it's the container itself
|
||||
else if (target.nodeName !== "button") {
|
||||
this.hovered = false;
|
||||
this.markup.navigate(this);
|
||||
event.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1544,7 +1541,11 @@ MarkupContainer.prototype = {
|
|||
// Recursively destroy children containers
|
||||
let firstChild;
|
||||
while (firstChild = this.children.firstChild) {
|
||||
firstChild.container.destroy();
|
||||
// Not all children of a container are containers themselves
|
||||
// ("show more nodes" button is one example)
|
||||
if (firstChild.container) {
|
||||
firstChild.container.destroy();
|
||||
}
|
||||
this.children.removeChild(firstChild);
|
||||
}
|
||||
|
||||
|
@ -1553,7 +1554,6 @@ MarkupContainer.prototype = {
|
|||
this.elt.removeEventListener("mouseover", this._onMouseOver, false);
|
||||
this.elt.removeEventListener("mouseout", this._onMouseOut, false);
|
||||
this.elt.removeEventListener("mousedown", this._onMouseDown, false);
|
||||
this.elt.removeEventListener("click", this._onClick, false);
|
||||
this.expander.removeEventListener("click", this._onToggle, false);
|
||||
|
||||
// Destroy my editor
|
||||
|
|
|
@ -6,6 +6,7 @@ support-files =
|
|||
browser_inspector_markup_navigation.html
|
||||
browser_inspector_markup_subset.html
|
||||
browser_inspector_markup_765105_tooltip.png
|
||||
browser_inspector_markup_950732.html
|
||||
head.js
|
||||
|
||||
[browser_bug896181_css_mixed_completion_new_attribute.js]
|
||||
|
@ -19,3 +20,4 @@ skip-if = true
|
|||
[browser_inspector_markup_navigation.js]
|
||||
[browser_inspector_markup_subset.js]
|
||||
[browser_inspector_markup_765105_tooltip.js]
|
||||
[browser_inspector_markup_950732.js]
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html class="html">
|
||||
<body class="body">
|
||||
<ul>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
<li>some content</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,105 @@
|
|||
/* Any copyright", " is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that the markup view loads only as many nodes as specified
|
||||
* by the devtools.markup.pagesize preference.
|
||||
*/
|
||||
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let promise = devtools.require("sdk/core/promise");
|
||||
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
|
||||
// Make sure nodes are hidden when there are more than 5 in a row
|
||||
registerCleanupFunction(function() {
|
||||
Services.prefs.clearUserPref("devtools.markup.pagesize");
|
||||
});
|
||||
Services.prefs.setIntPref("devtools.markup.pagesize", 5);
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let doc;
|
||||
let inspector;
|
||||
let markup;
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onload() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
|
||||
doc = content.document;
|
||||
waitForFocus(runTests, content);
|
||||
}, true);
|
||||
content.location = "http://mochi.test:8888/browser/browser/devtools/markupview/test/browser_inspector_markup_950732.html";
|
||||
|
||||
function runTests() {
|
||||
Task.spawn(function() {
|
||||
yield openMarkupView();
|
||||
yield selectUL();
|
||||
yield reloadPage();
|
||||
yield showAllNodes();
|
||||
|
||||
assertAllNodesAreVisible();
|
||||
finishUp();
|
||||
}).then(null, Cu.reportError);
|
||||
}
|
||||
|
||||
function openMarkupView() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
var target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let toolbox = gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
|
||||
inspector = toolbox.getCurrentPanel();
|
||||
markup = inspector.markup;
|
||||
inspector.once("inspector-updated", deferred.resolve);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function selectUL() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
let container = getContainerForRawNode(markup, doc.querySelector("ul"));
|
||||
let win = container.elt.ownerDocument.defaultView;
|
||||
|
||||
EventUtils.sendMouseEvent({type: "mousedown"}, container.elt, win);
|
||||
inspector.once("inspector-updated", deferred.resolve);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function reloadPage() {
|
||||
let deferred = promise.defer();
|
||||
|
||||
inspector.once("new-root", () => {
|
||||
doc = content.document;
|
||||
markup = inspector.markup;
|
||||
markup._waitForChildren().then(deferred.resolve);
|
||||
});
|
||||
content.location.reload();
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function showAllNodes() {
|
||||
let container = getContainerForRawNode(markup, doc.querySelector("ul"));
|
||||
let button = container.elt.querySelector("button");
|
||||
let win = button.ownerDocument.defaultView;
|
||||
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, win);
|
||||
return markup._waitForChildren();
|
||||
}
|
||||
|
||||
function assertAllNodesAreVisible() {
|
||||
let ul = doc.querySelector("ul");
|
||||
let container = getContainerForRawNode(markup, ul);
|
||||
ok(!container.elt.querySelector("button"), "All nodes button isn't here");
|
||||
is(container.children.childNodes.length, ul.children.length);
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
doc = inspector = markup = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -132,7 +132,10 @@ function test() {
|
|||
// Make sure that clicking the "more" button loads all the nodes.
|
||||
let container = getContainerForRawNode(markup, doc.querySelector("body"));
|
||||
let button = container.elt.querySelector("button");
|
||||
button.click();
|
||||
let win = button.ownerDocument.defaultView;
|
||||
|
||||
EventUtils.sendMouseEvent({type: "click"}, button, win);
|
||||
|
||||
markup._waitForChildren().then(() => {
|
||||
assertChildren("abcdefghijklmnopqrstuvwxyz");
|
||||
finishUp();
|
||||
|
|
|
@ -26,9 +26,10 @@ var StartUI = {
|
|||
document.getElementById("bcast_preciseInput").setAttribute("input",
|
||||
this.chromeWin.InputSourceHelper.isPrecise ? "precise" : "imprecise");
|
||||
|
||||
// NOTE: location.search doesn't work for about: pages
|
||||
if (location.href.indexOf("?firstrun") > 0) {
|
||||
let firstRunCount = Services.prefs.getIntPref("browser.firstrun.count");
|
||||
if (firstRunCount > 0) {
|
||||
document.loadOverlay("chrome://browser/content/FirstRunOverlay.xul", null);
|
||||
Services.prefs.setIntPref("browser.firstrun.count", firstRunCount - 1);
|
||||
}
|
||||
|
||||
this._adjustDOMforViewState(this.chromeWin.ContentAreaObserver.viewstate);
|
||||
|
|
|
@ -222,11 +222,6 @@ BrowserCLH.prototype = {
|
|||
// Default to the saved homepage
|
||||
let defaultURL = getHomePage();
|
||||
|
||||
// Show page for first run or upgrade.
|
||||
if (needHomepageOverride() == "new profile") {
|
||||
defaultURL = 'about:newtab?firstrun';
|
||||
}
|
||||
|
||||
// Override the default if we have a URL passed on command line
|
||||
if (uris.length > 0) {
|
||||
defaultURL = uris[0].spec;
|
||||
|
|
|
@ -121,6 +121,9 @@ pref("browser.display.history.maxresults", 100);
|
|||
/* max items per section of the startui */
|
||||
pref("browser.display.startUI.maxresults", 16);
|
||||
|
||||
// Number of times to display firstrun instructions on new tab page
|
||||
pref("browser.firstrun.count", 3);
|
||||
|
||||
// Backspace and Shift+Backspace behavior
|
||||
// 0 goes Back/Forward
|
||||
// 1 act like PgUp/PgDown
|
||||
|
|
|
@ -57,7 +57,8 @@
|
|||
#tabs > .tabs-scrollbox > .scrollbutton-up {
|
||||
list-style-image: url("images/tab-arrows.png") !important;
|
||||
-moz-image-region: rect(15px 58px 63px 14px) !important;
|
||||
padding-right: 13px;
|
||||
padding-right: 15px;
|
||||
width: @tabs_scrollarrow_width@;
|
||||
}
|
||||
#tabs > .tabs-scrollbox > .scrollbutton-up:hover {
|
||||
-moz-image-region: rect(14px 102px 62px 58px) !important;
|
||||
|
@ -72,7 +73,8 @@
|
|||
#tabs > .tabs-scrollbox > .scrollbutton-down {
|
||||
list-style-image: url("images/tab-arrows.png") !important;
|
||||
-moz-image-region: rect(73px 58px 121px 14px) !important;
|
||||
padding-left: 16px;
|
||||
padding-left: 15px;
|
||||
width: @tabs_scrollarrow_width@;
|
||||
}
|
||||
#tabs > .tabs-scrollbox > .scrollbutton-down:hover {
|
||||
-moz-image-region: rect(72px 102px 120px 58px) !important;
|
||||
|
@ -84,6 +86,30 @@
|
|||
-moz-image-region: rect(73px 196px 121px 152px) !important;
|
||||
}
|
||||
|
||||
.tabs-scrollbox > .scrollbutton-up:not([disabled]):not([collapsed])::after {
|
||||
content: "";
|
||||
visibility: visible;
|
||||
display: block;
|
||||
background-color: rgb(90, 91, 95);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: calc(@tabs_scrollarrow_width@ + @metro_spacing_normal@); /* .scrollbutton-up width + #tabs-container left padding */
|
||||
width: 1px;
|
||||
height: @tabs_height@;
|
||||
}
|
||||
|
||||
.tabs-scrollbox > .scrollbutton-down:not([disabled]):not([collapsed])::before {
|
||||
content: "";
|
||||
visibility: visible;
|
||||
display: block;
|
||||
background-color: rgb(90, 91, 95);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: calc(@tabs_scrollarrow_width@ + @newtab_button_width@); /* .scrollbutton-down width + #newtab-button width */
|
||||
width: 1px;
|
||||
height: @tabs_height@;
|
||||
}
|
||||
|
||||
#tabs-container[viewstate="snapped"] {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
@ -185,6 +211,7 @@ documenttab[selected] .documenttab-selection {
|
|||
|
||||
/* Add some extra padding for a larger target */
|
||||
padding: 18px 20px 30px 20px;
|
||||
width: @newtab_button_width@;
|
||||
}
|
||||
|
||||
/* Start UI ----------------------------------------------------------------- */
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
%define toolbar_height 69px
|
||||
%define labelled_toolbar_height 90px
|
||||
%define tabs_height 178px
|
||||
%define newtab_button_width 63px
|
||||
%define tabs_scrollarrow_width 64px
|
||||
%define findbar_height 54px
|
||||
|
||||
%define progress_height 5px
|
||||
|
|
|
@ -64,6 +64,18 @@ this.UITour = {
|
|||
},
|
||||
widgetName: "search-container",
|
||||
}],
|
||||
["selectedTabIcon", {
|
||||
query: (aDocument) => {
|
||||
let selectedtab = aDocument.defaultView.gBrowser.selectedTab;
|
||||
let element = aDocument.getAnonymousElementByAttribute(selectedtab,
|
||||
"anonid",
|
||||
"tab-icon-image");
|
||||
if (!element || !_isElementVisible(element)) {
|
||||
return null;
|
||||
}
|
||||
return element;
|
||||
},
|
||||
}],
|
||||
["urlbar", {
|
||||
query: "#urlbar",
|
||||
widgetName: "urlbar-container",
|
||||
|
@ -489,6 +501,10 @@ this.UITour = {
|
|||
highlighter.parentElement.openPopup(aTargetEl, "overlap", offsetX, offsetY);
|
||||
}
|
||||
|
||||
// Prevent showing a panel at an undefined position.
|
||||
if (!_isElementVisible(aTarget.node))
|
||||
return;
|
||||
|
||||
this._setAppMenuStateForAnnotation(aTarget.node.ownerDocument.defaultView, "highlight",
|
||||
this.targetIsInAppMenu(aTarget),
|
||||
showHighlightPanel.bind(this, aTarget.node));
|
||||
|
@ -527,6 +543,10 @@ this.UITour = {
|
|||
tooltip.openPopup(aAnchorEl, alignment);
|
||||
}
|
||||
|
||||
// Prevent showing a panel at an undefined position.
|
||||
if (!_isElementVisible(aAnchor.node))
|
||||
return;
|
||||
|
||||
this._setAppMenuStateForAnnotation(aAnchor.node.ownerDocument.defaultView, "info",
|
||||
this.targetIsInAppMenu(aAnchor),
|
||||
showInfoPanel.bind(this, aAnchor.node));
|
||||
|
@ -615,3 +635,8 @@ this.UITour = {
|
|||
aWindow.gBrowser.selectedTab = tab;
|
||||
},
|
||||
};
|
||||
|
||||
function _isElementVisible(aElement) {
|
||||
let targetStyle = aElement.ownerDocument.defaultView.getComputedStyle(aElement);
|
||||
return (targetStyle.display != "none" && targetStyle.visibility == "visible");
|
||||
}
|
||||
|
|
|
@ -245,6 +245,11 @@ if test -n "$gonkdir" ; then
|
|||
MOZ_B2G_CAMERA=1
|
||||
MOZ_OMX_DECODER=1
|
||||
AC_SUBST(MOZ_OMX_DECODER)
|
||||
;;
|
||||
19)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include"
|
||||
MOZ_NFC=1
|
||||
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
|
||||
|
|
|
@ -324,10 +324,13 @@ MovieFragmentBox::MovieFragmentBox(uint32_t aType, ISOControl* aControl)
|
|||
, mTrackType(aType)
|
||||
{
|
||||
boxes.AppendElement(new MovieFragmentHeaderBox(mTrackType, aControl));
|
||||
|
||||
// Always adds flags_data_offset_present in each TrackFragmentBox, Android
|
||||
// parser requires this flag to calculate the correct bitstream offset.
|
||||
if (mTrackType & Audio_Track) {
|
||||
boxes.AppendElement(
|
||||
new TrackFragmentBox(Audio_Track,
|
||||
flags_sample_size_present,
|
||||
flags_sample_size_present | flags_data_offset_present,
|
||||
aControl));
|
||||
}
|
||||
if (mTrackType & Video_Track) {
|
||||
|
|
|
@ -688,10 +688,11 @@ BrowserElementChild.prototype = {
|
|||
let self = this;
|
||||
let maxWidth = data.json.args.width;
|
||||
let maxHeight = data.json.args.height;
|
||||
let mimeType = data.json.args.mimeType;
|
||||
let domRequestID = data.json.id;
|
||||
|
||||
let takeScreenshotClosure = function() {
|
||||
self._takeScreenshot(maxWidth, maxHeight, domRequestID);
|
||||
self._takeScreenshot(maxWidth, maxHeight, mimeType, domRequestID);
|
||||
};
|
||||
|
||||
let maxDelayMS = 2000;
|
||||
|
@ -712,7 +713,7 @@ BrowserElementChild.prototype = {
|
|||
* the desired maxWidth and maxHeight, and given the DOMRequest ID associated
|
||||
* with the request from the parent.
|
||||
*/
|
||||
_takeScreenshot: function(maxWidth, maxHeight, domRequestID) {
|
||||
_takeScreenshot: function(maxWidth, maxHeight, mimeType, domRequestID) {
|
||||
// You can think of the screenshotting algorithm as carrying out the
|
||||
// following steps:
|
||||
//
|
||||
|
@ -728,10 +729,14 @@ BrowserElementChild.prototype = {
|
|||
// - Crop the viewport so its width is no larger than maxWidth and its
|
||||
// height is no larger than maxHeight.
|
||||
//
|
||||
// - Set mozOpaque to true and background color to solid white
|
||||
// if we are taking a JPEG screenshot, keep transparent if otherwise.
|
||||
//
|
||||
// - Return a screenshot of the page's viewport scaled and cropped per
|
||||
// above.
|
||||
debug("Taking a screenshot: maxWidth=" + maxWidth +
|
||||
", maxHeight=" + maxHeight +
|
||||
", mimeType=" + mimeType +
|
||||
", domRequestID=" + domRequestID + ".");
|
||||
|
||||
if (!content) {
|
||||
|
@ -749,19 +754,22 @@ BrowserElementChild.prototype = {
|
|||
let canvasWidth = Math.min(maxWidth, Math.round(content.innerWidth * scale));
|
||||
let canvasHeight = Math.min(maxHeight, Math.round(content.innerHeight * scale));
|
||||
|
||||
let transparent = (mimeType !== 'image/jpeg');
|
||||
|
||||
var canvas = content.document
|
||||
.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
||||
canvas.mozOpaque = true;
|
||||
if (!transparent)
|
||||
canvas.mozOpaque = true;
|
||||
canvas.width = canvasWidth;
|
||||
canvas.height = canvasHeight;
|
||||
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.scale(scale, scale);
|
||||
ctx.drawWindow(content, 0, 0, content.innerWidth, content.innerHeight,
|
||||
"rgb(255,255,255)");
|
||||
transparent ? "rgba(255,255,255,0)" : "rgb(255,255,255)");
|
||||
|
||||
// Take a JPEG screenshot to hack around the fact that we can't specify
|
||||
// opaque PNG. This requires us to unpremultiply the alpha channel, which
|
||||
// Take a JPEG screenshot by default instead of PNG with alpha channel.
|
||||
// This requires us to unpremultiply the alpha channel, which
|
||||
// is expensive on ARM processors because they lack a hardware integer
|
||||
// division instruction.
|
||||
canvas.toBlob(function(blob) {
|
||||
|
@ -769,7 +777,7 @@ BrowserElementChild.prototype = {
|
|||
id: domRequestID,
|
||||
successRv: blob
|
||||
});
|
||||
}, 'image/jpeg');
|
||||
}, mimeType);
|
||||
},
|
||||
|
||||
_recvFireCtxCallback: function(data) {
|
||||
|
|
|
@ -547,16 +547,19 @@ BrowserElementParent.prototype = {
|
|||
return this._sendDOMRequest('purge-history');
|
||||
},
|
||||
|
||||
_getScreenshot: function(_width, _height) {
|
||||
_getScreenshot: function(_width, _height, _mimeType) {
|
||||
let width = parseInt(_width);
|
||||
let height = parseInt(_height);
|
||||
let mimeType = (typeof _mimeType === 'string') ?
|
||||
_mimeType.trim().toLowerCase() : 'image/jpeg';
|
||||
if (isNaN(width) || isNaN(height) || width < 0 || height < 0) {
|
||||
throw Components.Exception("Invalid argument",
|
||||
Cr.NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
return this._sendDOMRequest('get-screenshot',
|
||||
{width: width, height: height});
|
||||
{width: width, height: height,
|
||||
mimeType: mimeType});
|
||||
},
|
||||
|
||||
_recvNextPaint: function(data) {
|
||||
|
|
|
@ -15,20 +15,30 @@ function runTest() {
|
|||
iframe1.src = 'data:text/html,<html>' +
|
||||
'<body style="background:green">hello</body></html>';
|
||||
|
||||
var screenshotArrayBuffers = [];
|
||||
var screenshotImageDatas = [];
|
||||
var numLoaded = 0;
|
||||
|
||||
function screenshotTaken(screenshotArrayBuffer) {
|
||||
screenshotArrayBuffers.push(screenshotArrayBuffer);
|
||||
if (screenshotArrayBuffers.length === 1) {
|
||||
function screenshotTaken(screenshotImageData) {
|
||||
screenshotImageDatas.push(screenshotImageData);
|
||||
if (screenshotImageDatas.length === 1) {
|
||||
ok(true, 'Got initial non blank screenshot');
|
||||
iframe1.src = 'data:text/html,<html>' +
|
||||
'<body style="background:blue">hello</body></html>';
|
||||
|
||||
// Wait until screenshotArrayBuffer !== screenshotArrayBuffers[0].
|
||||
waitForScreenshot(function(screenshotArrayBuffer) {
|
||||
var view1 = new Int8Array(screenshotArrayBuffer);
|
||||
var view2 = new Int8Array(screenshotArrayBuffers[0]);
|
||||
var view = screenshotImageData.data;
|
||||
if (view[3] !== 255) {
|
||||
ok(false, 'The first pixel of initial screenshot is not opaque');
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
ok(true, 'Verified the first pixel of initial screenshot is opaque');
|
||||
|
||||
iframe1.src = 'data:text/html,<html>' +
|
||||
'<body style="background:transparent">hello</body></html>';
|
||||
|
||||
// Wait until screenshotImageData !== screenshotImageDatas[0].
|
||||
waitForScreenshot(function(screenshotImageData) {
|
||||
var view1 = screenshotImageData.data;
|
||||
var view2 = screenshotImageDatas[0].data;
|
||||
|
||||
if (view1.length != view2.length) {
|
||||
return true;
|
||||
}
|
||||
|
@ -40,51 +50,101 @@ function runTest() {
|
|||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}, 'image/png');
|
||||
}
|
||||
else if (screenshotArrayBuffers.length === 2) {
|
||||
else if (screenshotImageDatas.length === 2) {
|
||||
ok(true, 'Got updated screenshot after source page changed');
|
||||
|
||||
var view = screenshotImageData.data;
|
||||
if (view[3] !== 0) {
|
||||
// The case here will always fail when oop'd on Firefox Desktop,
|
||||
// but not on B2G Emulator
|
||||
// See https://bugzil.la/878003#c20
|
||||
|
||||
var isB2G = (navigator.platform === '');
|
||||
info('navigator.platform: ' + navigator.platform);
|
||||
if (!isB2G && browserElementTestHelpers.getOOPByDefaultPref()) {
|
||||
todo(false, 'The first pixel of updated screenshot is not transparent');
|
||||
} else {
|
||||
ok(false, 'The first pixel of updated screenshot is not transparent');
|
||||
}
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
ok(true, 'Verified the first pixel of updated screenshot is transparent');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
// We continually take screenshots until we get one that we are
|
||||
// happy with.
|
||||
function waitForScreenshot(filter) {
|
||||
function gotScreenshotArrayBuffer() {
|
||||
// |this| is the FileReader whose result contains the screenshot as an
|
||||
// ArrayBuffer.
|
||||
function waitForScreenshot(filter, mimeType) {
|
||||
function gotImage(e) {
|
||||
// |this| is the Image.
|
||||
|
||||
URL.revokeObjectURL(this.src);
|
||||
|
||||
if (e.type === 'error' || !this.width || !this.height) {
|
||||
tryAgain();
|
||||
|
||||
if (filter(this.result)) {
|
||||
screenshotTaken(this.result);
|
||||
return;
|
||||
}
|
||||
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = canvas.height = 1000;
|
||||
var ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(this, 0, 0);
|
||||
var imageData = ctx.getImageData(0, 0, 1000, 1000);
|
||||
|
||||
if (filter(imageData)) {
|
||||
screenshotTaken(imageData);
|
||||
return;
|
||||
}
|
||||
tryAgain();
|
||||
}
|
||||
|
||||
function tryAgain() {
|
||||
if (--attempts === 0) {
|
||||
ok(false, 'Timed out waiting for correct screenshot');
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
iframe1.getScreenshot(1000, 1000).onsuccess = getScreenshotArrayBuffer;
|
||||
iframe1.getScreenshot(1000, 1000, mimeType).onsuccess =
|
||||
getScreenshotImageData;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
function getScreenshotArrayBuffer(e) {
|
||||
var fr = new FileReader();
|
||||
fr.onloadend = gotScreenshotArrayBuffer;
|
||||
fr.readAsArrayBuffer(e.target.result);
|
||||
function getScreenshotImageData(e) {
|
||||
var blob = e.target.result;
|
||||
if (blob.type !== mimeType) {
|
||||
ok(false, 'MIME type of screenshot taken incorrect');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
if (blob.size === 0) {
|
||||
tryAgain();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var img = new Image();
|
||||
img.src = URL.createObjectURL(blob);
|
||||
img.onload = img.onerror = gotImage;
|
||||
}
|
||||
|
||||
var attempts = 10;
|
||||
iframe1.getScreenshot(1000, 1000).onsuccess = getScreenshotArrayBuffer;
|
||||
iframe1.getScreenshot(1000, 1000, mimeType).onsuccess =
|
||||
getScreenshotImageData;
|
||||
}
|
||||
|
||||
function iframeLoadedHandler() {
|
||||
numLoaded++;
|
||||
if (numLoaded === 2) {
|
||||
waitForScreenshot(function(screenshotArrayBuffer) {
|
||||
return screenshotArrayBuffer.byteLength != 0;
|
||||
});
|
||||
waitForScreenshot(function(screenshotImageData) {
|
||||
return true;
|
||||
}, 'image/jpeg');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=753595
|
|||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753595">Mozilla Bug 753595</a>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=878003">Mozilla Bug 878003</a>
|
||||
|
||||
<script type="application/javascript;version=1.7" src='browserElement_GetScreenshot.js'>
|
||||
</script>
|
||||
|
|
|
@ -428,19 +428,26 @@ this.NetworkStatsService = {
|
|||
debug("clear stats for network " + network.id + " of type " + network.type);
|
||||
|
||||
if (!this._networks[netId]) {
|
||||
let error = "Invalid networkType";
|
||||
let result = null;
|
||||
|
||||
// Check if network is valid but has not established a connection yet.
|
||||
// Check if network is valid but has not established a connection yet. If it is not
|
||||
// found in RIL networks, it can be a SIM network used in the past having sample
|
||||
// in the database.
|
||||
let rilNetworks = this.getRilNetworks();
|
||||
if (rilNetworks[netId]) {
|
||||
error = null;
|
||||
result = true;
|
||||
}
|
||||
if (!rilNetworks[netId]) {
|
||||
// Check if it is available in the DB.
|
||||
this._db.isNetworkAvailable(network, function(aError, aResult) {
|
||||
if (aResult) {
|
||||
this._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: aError, result: aResult });
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: error, result: result });
|
||||
return;
|
||||
mm.sendAsyncMessage("NetworkStats:Clear:Return",
|
||||
{ id: msg.id, error: "Invalid networkType", result: null });
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this._db.clearInterfaceStats(network, function onDBCleared(aError, aResult) {
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "nsString.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "mozJSComponentLoader.h"
|
||||
|
||||
|
@ -91,6 +92,21 @@ struct Paths {
|
|||
* the same as homeDir.
|
||||
*/
|
||||
nsString desktopDir;
|
||||
/**
|
||||
* The user's 'application data' directory.
|
||||
* Windows:
|
||||
* HOME = Documents and Settings\$USER\Application Data
|
||||
* UAppData = $HOME[\$vendor]\$name
|
||||
*
|
||||
* Unix:
|
||||
* HOME = ~
|
||||
* UAppData = $HOME/.[$vendor/]$name
|
||||
*
|
||||
* Mac:
|
||||
* HOME = ~
|
||||
* UAppData = $HOME/Library/Application Support/$name
|
||||
*/
|
||||
nsString userApplicationDataDir;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
/**
|
||||
|
@ -123,6 +139,7 @@ struct Paths {
|
|||
localProfileDir.SetIsVoid(true);
|
||||
homeDir.SetIsVoid(true);
|
||||
desktopDir.SetIsVoid(true);
|
||||
userApplicationDataDir.SetIsVoid(true);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
winAppDataDir.SetIsVoid(true);
|
||||
|
@ -218,7 +235,7 @@ nsresult InitOSFileConstants()
|
|||
|
||||
// Initialize paths->libDir
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_GetSpecialDirectory("XpcomLib", getter_AddRefs(file));
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_XPCOM_LIBRARY_FILE, getter_AddRefs(file));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -262,6 +279,7 @@ nsresult InitOSFileConstants()
|
|||
GetPathToSpecialDir(NS_OS_TEMP_DIR, paths->tmpDir);
|
||||
GetPathToSpecialDir(NS_OS_HOME_DIR, paths->homeDir);
|
||||
GetPathToSpecialDir(NS_OS_DESKTOP_DIR, paths->desktopDir);
|
||||
GetPathToSpecialDir(XRE_USER_APP_DATA_DIR, paths->userApplicationDataDir);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
GetPathToSpecialDir(NS_WIN_APPDATA_DIR, paths->winAppDataDir);
|
||||
|
@ -857,6 +875,10 @@ bool DefineOSFileConstants(JSContext *cx, JS::Handle<JSObject*> global)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!SetStringProperty(cx, objPath, "userApplicationDataDir", gPaths->userApplicationDataDir)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
if (!SetStringProperty(cx, objPath, "winAppDataDir", gPaths->winAppDataDir)) {
|
||||
return false;
|
||||
|
|
|
@ -694,7 +694,27 @@ function RadioInterfaceLayer() {
|
|||
let options = {
|
||||
debug: debugPref,
|
||||
cellBroadcastDisabled: false,
|
||||
clirMode: RIL.CLIR_DEFAULT
|
||||
clirMode: RIL.CLIR_DEFAULT,
|
||||
quirks: {
|
||||
callstateExtraUint32:
|
||||
libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
|
||||
v5Legacy:
|
||||
libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true",
|
||||
requestUseDialEmergencyCall:
|
||||
libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
|
||||
simAppStateExtraFields:
|
||||
libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true",
|
||||
extraUint2ndCall:
|
||||
libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") == "true",
|
||||
haveQueryIccLockRetryCount:
|
||||
libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true",
|
||||
sendStkProfileDownload:
|
||||
libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
|
||||
dataRegistrationOnDemand:
|
||||
libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true"
|
||||
},
|
||||
rilEmergencyNumbers: libcutils.property_get("ril.ecclist") ||
|
||||
libcutils.property_get("ro.ril.ecclist")
|
||||
};
|
||||
|
||||
try {
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
importScripts("ril_consts.js", "systemlibs.js");
|
||||
importScripts("ril_consts.js");
|
||||
importScripts("resource://gre/modules/workers/require.js");
|
||||
|
||||
// set to true in ril_consts.js to see debug messages
|
||||
|
@ -53,6 +53,7 @@ if (!this.debug) {
|
|||
};
|
||||
}
|
||||
|
||||
let RIL_EMERGENCY_NUMBERS;
|
||||
const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
|
||||
|
||||
// Timeout value for emergency callback mode.
|
||||
|
@ -74,23 +75,22 @@ const MMI_MAX_LENGTH_SHORT_CODE = 2;
|
|||
|
||||
const MMI_END_OF_USSD = "#";
|
||||
|
||||
let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true";
|
||||
let RILQUIRKS_CALLSTATE_EXTRA_UINT32;
|
||||
// This may change at runtime since in RIL v6 and later, we get the version
|
||||
// number via the UNSOLICITED_RIL_CONNECTED parcel.
|
||||
let RILQUIRKS_V5_LEGACY = libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true";
|
||||
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true";
|
||||
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true";
|
||||
let RILQUIRKS_V5_LEGACY;
|
||||
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL;
|
||||
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS;
|
||||
// Needed for call-waiting on Peak device
|
||||
let RILQUIRKS_EXTRA_UINT32_2ND_CALL = libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") == "true";
|
||||
let RILQUIRKS_EXTRA_UINT32_2ND_CALL;
|
||||
// On the emulator we support querying the number of lock retries
|
||||
let RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true";
|
||||
let RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT;
|
||||
|
||||
// Ril quirk to Send STK Profile Download
|
||||
let RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true";
|
||||
let RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD;
|
||||
|
||||
// Ril quirk to attach data registration on demand.
|
||||
let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND =
|
||||
libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true";
|
||||
let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND;
|
||||
|
||||
// Marker object.
|
||||
let PENDING_NETWORK_TYPE = {};
|
||||
|
@ -111,7 +111,7 @@ let Buf = {
|
|||
|
||||
// Maps tokens we send out with requests to the request type, so that
|
||||
// when we get a response parcel back, we know what request it was for.
|
||||
this.mTokenRequestMap = {};
|
||||
this.mTokenRequestMap = new Map();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -125,7 +125,7 @@ let Buf = {
|
|||
let token = this.readInt32();
|
||||
let error = this.readInt32();
|
||||
|
||||
options = this.mTokenRequestMap[token];
|
||||
options = this.mTokenRequestMap.get(token);
|
||||
if (!options) {
|
||||
if (DEBUG) {
|
||||
debug("Suspicious uninvited request found: " + token + ". Ignored!");
|
||||
|
@ -133,7 +133,7 @@ let Buf = {
|
|||
return;
|
||||
}
|
||||
|
||||
delete this.mTokenRequestMap[token];
|
||||
this.mTokenRequestMap.delete(token);
|
||||
request_type = options.rilRequestType;
|
||||
|
||||
options.rilRequestError = error;
|
||||
|
@ -174,7 +174,7 @@ let Buf = {
|
|||
}
|
||||
options.rilRequestType = type;
|
||||
options.rilRequestError = null;
|
||||
this.mTokenRequestMap[this.mToken] = options;
|
||||
this.mTokenRequestMap.set(this.mToken, options);
|
||||
this.mToken++;
|
||||
return this.mToken;
|
||||
},
|
||||
|
@ -2912,12 +2912,8 @@ let RIL = {
|
|||
* The number to look up.
|
||||
*/
|
||||
_isEmergencyNumber: function(number) {
|
||||
// Check read-write ecclist property first.
|
||||
let numbers = libcutils.property_get("ril.ecclist");
|
||||
if (!numbers) {
|
||||
// Then read-only ecclist property since others RIL only uses this.
|
||||
numbers = libcutils.property_get("ro.ril.ecclist");
|
||||
}
|
||||
// Check ril provided numbers first.
|
||||
let numbers = RIL_EMERGENCY_NUMBERS;
|
||||
|
||||
if (numbers) {
|
||||
numbers = numbers.split(",");
|
||||
|
@ -3585,11 +3581,8 @@ let RIL = {
|
|||
}
|
||||
|
||||
// Set flag for outgoing emergency call.
|
||||
if (newCall.isOutgoing && this._isEmergencyNumber(newCall.number)) {
|
||||
newCall.isEmergency = true;
|
||||
} else {
|
||||
newCall.isEmergency = false;
|
||||
}
|
||||
newCall.isEmergency = newCall.isOutgoing &&
|
||||
this._isEmergencyNumber(newCall.number);
|
||||
|
||||
// Add to our map.
|
||||
if (newCall.isMpty) {
|
||||
|
@ -4962,6 +4955,16 @@ let RIL = {
|
|||
CLIENT_ID = options.clientId;
|
||||
this.cellBroadcastDisabled = options.cellBroadcastDisabled;
|
||||
this.clirMode = options.clirMode;
|
||||
RIL_EMERGENCY_NUMBERS = options.rilEmergencyNumbers;
|
||||
let quirks = options.quirks;
|
||||
RILQUIRKS_CALLSTATE_EXTRA_UINT32 = quirks.callstateExtraUint32;
|
||||
RILQUIRKS_V5_LEGACY = quirks.v5Legacy;
|
||||
RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = quirks.requestUseDialEmergencyCall;
|
||||
RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = quirks.simAppStateExtraFields;
|
||||
RILQUIRKS_EXTRA_UINT32_2ND_CALL = quirks.extraUint2ndCall;
|
||||
RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
|
||||
RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
|
||||
RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -310,11 +310,16 @@ this.WifiCommand = function(aControlMessage, aInterface) {
|
|||
doBooleanCommand("BLACKLIST clear", "OK", callback);
|
||||
};
|
||||
|
||||
command.setSuspendOptimizations = function (enabled, callback) {
|
||||
command.setSuspendOptimizationsICS = function (enabled, callback) {
|
||||
doBooleanCommand("DRIVER SETSUSPENDOPT " + (enabled ? 0 : 1),
|
||||
"OK", callback);
|
||||
};
|
||||
|
||||
command.setSuspendOptimizationsJB = function (enabled, callback) {
|
||||
doBooleanCommand("DRIVER SETSUSPENDMODE " + (enabled ? 1 : 0),
|
||||
"OK", callback);
|
||||
};
|
||||
|
||||
command.connectToSupplicant = function(callback) {
|
||||
voidControlMessage("connect_to_supplicant", callback);
|
||||
};
|
||||
|
|
|
@ -1156,7 +1156,9 @@ var WifiManager = (function() {
|
|||
manager.getHttpProxyNetwork = getHttpProxyNetwork;
|
||||
manager.setHttpProxy = setHttpProxy;
|
||||
manager.configureHttpProxy = configureHttpProxy;
|
||||
manager.setSuspendOptimizations = wifiCommand.setSuspendOptimizations;
|
||||
manager.setSuspendOptimizations = (sdkVersion >= 16)
|
||||
? wifiCommand.setSuspendOptimizationsJB
|
||||
: wifiCommand.setSuspendOptimizationsICS;
|
||||
manager.setStaticIpMode = setStaticIpMode;
|
||||
manager.getRssiApprox = wifiCommand.getRssiApprox;
|
||||
manager.getLinkSpeed = wifiCommand.getLinkSpeed;
|
||||
|
|
|
@ -44,13 +44,33 @@ void
|
|||
ParamTraits<MagicGrallocBufferHandle>::Write(Message* aMsg,
|
||||
const paramType& aParam)
|
||||
{
|
||||
#if ANDROID_VERSION >= 19
|
||||
sp<GraphicBuffer> flattenable = aParam.mGraphicBuffer;
|
||||
#else
|
||||
Flattenable *flattenable = aParam.mGraphicBuffer.get();
|
||||
#endif
|
||||
size_t nbytes = flattenable->getFlattenedSize();
|
||||
size_t nfds = flattenable->getFdCount();
|
||||
|
||||
char data[nbytes];
|
||||
int fds[nfds];
|
||||
|
||||
#if ANDROID_VERSION >= 19
|
||||
// Make a copy of "data" and "fds" for flatten() to avoid casting problem
|
||||
void *pdata = (void *)data;
|
||||
int *pfds = fds;
|
||||
|
||||
flattenable->flatten(pdata, nbytes, pfds, nfds);
|
||||
|
||||
// In Kitkat, flatten() will change the value of nbytes and nfds, which dues
|
||||
// to multiple parcelable object consumption. The actual size and fd count
|
||||
// which returned by getFlattenedSize() and getFdCount() are not changed.
|
||||
// So we change nbytes and nfds back by call corresponding calls.
|
||||
nbytes = flattenable->getFlattenedSize();
|
||||
nfds = flattenable->getFdCount();
|
||||
#else
|
||||
flattenable->flatten(data, nbytes, fds, nfds);
|
||||
#endif
|
||||
|
||||
aMsg->WriteSize(nbytes);
|
||||
aMsg->WriteSize(nfds);
|
||||
|
@ -96,9 +116,17 @@ ParamTraits<MagicGrallocBufferHandle>::Read(const Message* aMsg,
|
|||
}
|
||||
|
||||
sp<GraphicBuffer> buffer(new GraphicBuffer());
|
||||
#if ANDROID_VERSION >= 19
|
||||
// Make a copy of "data" and "fds" for unflatten() to avoid casting problem
|
||||
void const *pdata = (void const *)data;
|
||||
int const *pfds = fds;
|
||||
|
||||
if (NO_ERROR == buffer->unflatten(pdata, nbytes, pfds, nfds)) {
|
||||
#else
|
||||
Flattenable *flattenable = buffer.get();
|
||||
|
||||
if (NO_ERROR == flattenable->unflatten(data, nbytes, fds, nfds)) {
|
||||
#endif
|
||||
aResult->mGraphicBuffer = buffer;
|
||||
return true;
|
||||
}
|
||||
|
@ -128,8 +156,6 @@ ImageFormatForPixelFormat(android::PixelFormat aFormat)
|
|||
return gfxImageFormatRGB24;
|
||||
case PIXEL_FORMAT_RGB_565:
|
||||
return gfxImageFormatRGB16_565;
|
||||
case PIXEL_FORMAT_A_8:
|
||||
return gfxImageFormatA8;
|
||||
default:
|
||||
MOZ_CRASH("Unknown gralloc pixel format");
|
||||
}
|
||||
|
@ -146,8 +172,6 @@ PixelFormatForImageFormat(gfxImageFormat aFormat)
|
|||
return android::PIXEL_FORMAT_RGBX_8888;
|
||||
case gfxImageFormatRGB16_565:
|
||||
return android::PIXEL_FORMAT_RGB_565;
|
||||
case gfxImageFormatA8:
|
||||
return android::PIXEL_FORMAT_A_8;
|
||||
default:
|
||||
MOZ_CRASH("Unknown gralloc pixel format");
|
||||
}
|
||||
|
@ -168,8 +192,6 @@ BytesPerPixelForPixelFormat(android::PixelFormat aFormat)
|
|||
case PIXEL_FORMAT_RGBA_5551:
|
||||
case PIXEL_FORMAT_RGBA_4444:
|
||||
return 2;
|
||||
case PIXEL_FORMAT_A_8:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -229,9 +229,6 @@ GrallocTextureClientOGL::AllocateForSurface(gfx::IntSize aSize,
|
|||
case gfx::SurfaceFormat::R5G6B5:
|
||||
format = android::PIXEL_FORMAT_RGB_565;
|
||||
break;
|
||||
case gfx::SurfaceFormat::A8:
|
||||
format = android::PIXEL_FORMAT_A_8;
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Unsupported surface format");
|
||||
return false;
|
||||
|
|
|
@ -31,8 +31,6 @@ SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
|
|||
return swapRB ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::R8G8B8X8;
|
||||
case android::PIXEL_FORMAT_RGB_565:
|
||||
return gfx::SurfaceFormat::R5G6B5;
|
||||
case android::PIXEL_FORMAT_A_8:
|
||||
return gfx::SurfaceFormat::A8;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||
case HAL_PIXEL_FORMAT_YCbCr_422_I:
|
||||
|
@ -71,7 +69,6 @@ TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
|
|||
case android::PIXEL_FORMAT_RGBA_8888:
|
||||
case android::PIXEL_FORMAT_RGBX_8888:
|
||||
case android::PIXEL_FORMAT_RGB_565:
|
||||
case android::PIXEL_FORMAT_A_8:
|
||||
return LOCAL_GL_TEXTURE_2D;
|
||||
default:
|
||||
if (aFormat >= 0x100 && aFormat <= 0x1FF) {
|
||||
|
|
|
@ -1262,8 +1262,6 @@ Deprecated_SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
|
|||
return swapRB ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::R8G8B8X8;
|
||||
case android::PIXEL_FORMAT_RGB_565:
|
||||
return SurfaceFormat::R5G6B5;
|
||||
case android::PIXEL_FORMAT_A_8:
|
||||
return SurfaceFormat::A8;
|
||||
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
|
||||
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
|
||||
case HAL_PIXEL_FORMAT_YCbCr_422_I:
|
||||
|
@ -1301,7 +1299,6 @@ Deprecated_TextureTargetForAndroidPixelFormat(android::PixelFormat aFormat)
|
|||
case android::PIXEL_FORMAT_RGBA_8888:
|
||||
case android::PIXEL_FORMAT_RGBX_8888:
|
||||
case android::PIXEL_FORMAT_RGB_565:
|
||||
case android::PIXEL_FORMAT_A_8:
|
||||
return LOCAL_GL_TEXTURE_2D;
|
||||
default:
|
||||
if (aFormat >= 0x100 && aFormat <= 0x1FF) {
|
||||
|
|
|
@ -592,8 +592,6 @@ LinearScanAllocator::populateSafepoints()
|
|||
if (payloadAlloc->isArgument() &&
|
||||
(!payload->canonicalSpill() || payload->canonicalSpill() == payloadAlloc))
|
||||
{
|
||||
JS_ASSERT(typeAlloc->isArgument());
|
||||
JS_ASSERT(!type->canonicalSpill() || type->canonicalSpill() == typeAlloc);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||
private RenderContext mLastPageContext;
|
||||
private int mMaxTextureSize;
|
||||
private int mBackgroundColor;
|
||||
private int mOverscrollColor;
|
||||
|
||||
private long mLastFrameTime;
|
||||
private final CopyOnWriteArrayList<RenderTask> mTasks;
|
||||
|
@ -134,6 +135,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||
|
||||
public LayerRenderer(LayerView view) {
|
||||
mView = view;
|
||||
mOverscrollColor = view.getContext().getResources().getColor(R.color.background_normal);
|
||||
|
||||
Bitmap scrollbarImage = view.getScrollbarImage();
|
||||
IntSize size = new IntSize(scrollbarImage.getWidth(), scrollbarImage.getHeight());
|
||||
|
@ -587,6 +589,9 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||
|
||||
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
|
||||
|
||||
// Draw the overscroll background area as a solid color
|
||||
clear(mOverscrollColor);
|
||||
|
||||
// Update background color.
|
||||
mBackgroundColor = mView.getBackgroundColor();
|
||||
|
||||
|
|
|
@ -62,6 +62,23 @@ import java.util.ArrayList;
|
|||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@code BrowserToolbar} is single entry point for users of the toolbar
|
||||
* subsystem i.e. this should be the only import outside the 'toolbar'
|
||||
* package.
|
||||
*
|
||||
* {@code BrowserToolbar} serves at the single event bus for all
|
||||
* sub-components in the toolbar. It tracks tab events and gecko messages
|
||||
* and update the state of its inner components accordingly.
|
||||
*
|
||||
* It has two states, display and edit, which are controlled by
|
||||
* ToolbarEditLayout and ToolbarDisplayLayout. In display state, the toolbar
|
||||
* displays the current state for the selected tab. In edit state, it shows
|
||||
* a text entry for searching bookmarks/history. {@code BrowserToolbar}
|
||||
* provides public API to enter, cancel, and commit the edit state as well
|
||||
* as a set of listeners to allow {@code BrowserToolbar} users to react
|
||||
* to state changes accordingly.
|
||||
*/
|
||||
public class BrowserToolbar extends GeckoRelativeLayout
|
||||
implements Tabs.OnTabsChangedListener,
|
||||
GeckoMenu.ActionItemBarPresenter,
|
||||
|
|
|
@ -47,17 +47,38 @@ import java.util.Arrays;
|
|||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@code ToolbarDisplayLayout} is the UI for when the toolbar is in
|
||||
* display state. It's used to display the state of the currently selected
|
||||
* tab. It should always be updated through a single entry point
|
||||
* (updateFromTab) and should never track any tab events or gecko messages
|
||||
* on its own to keep it as dumb as possible.
|
||||
*
|
||||
* The UI has two possible modes: progress and display which are triggered
|
||||
* when UpdateFlags.PROGRESS is used depending on the current tab state.
|
||||
* The progress mode is triggered when the tab is loading a page. Display mode
|
||||
* is used otherwise.
|
||||
*
|
||||
* {@code ToolbarDisplayLayout} is meant to be owned by {@code BrowserToolbar}
|
||||
* which is the main event bus for the toolbar subsystem.
|
||||
*/
|
||||
public class ToolbarDisplayLayout extends GeckoLinearLayout
|
||||
implements Animation.AnimationListener {
|
||||
|
||||
private static final String LOGTAG = "GeckoToolbarDisplayLayout";
|
||||
|
||||
// To be used with updateFromTab() to allow the caller
|
||||
// to give enough context for the requested state change.
|
||||
enum UpdateFlags {
|
||||
TITLE,
|
||||
FAVICON,
|
||||
PROGRESS,
|
||||
SITE_IDENTITY,
|
||||
PRIVATE_MODE,
|
||||
|
||||
// Disable any animation that might be
|
||||
// triggered from this state change. Mostly
|
||||
// used on tab switches, see BrowserToolbar.
|
||||
DISABLE_ANIMATIONS
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,12 @@ import android.view.View.OnFocusChangeListener;
|
|||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
/**
|
||||
* {@code ToolbarEditLayout} is the UI for when the toolbar is in
|
||||
* edit state. It controls a text entry ({@code ToolbarEditText})
|
||||
* and its matching 'go' button which changes depending on the
|
||||
* current type of text in the entry.
|
||||
*/
|
||||
public class ToolbarEditLayout extends GeckoLinearLayout {
|
||||
|
||||
private final ToolbarEditText mEditText;
|
||||
|
|
|
@ -30,11 +30,20 @@ import android.view.View.OnKeyListener;
|
|||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
/**
|
||||
* {@code ToolbarEditText} is the text entry used when the toolbar
|
||||
* is in edit state. It handles all the necessary input method machinery
|
||||
* as well as the tracking of different text types (empty, search, or url).
|
||||
* It's meant to be owned by {@code ToolbarEditLayout}.
|
||||
*/
|
||||
public class ToolbarEditText extends CustomEditText
|
||||
implements AutocompleteHandler {
|
||||
|
||||
private static final String LOGTAG = "GeckoToolbarEditText";
|
||||
|
||||
// Used to track the current type of content in the
|
||||
// text entry so that ToolbarEditLayout can update its
|
||||
// state accordingly.
|
||||
enum TextType {
|
||||
EMPTY,
|
||||
SEARCH_QUERY,
|
||||
|
|
|
@ -602,7 +602,6 @@ void RTSPSource::onDisconnected(const sp<AMessage> &msg) {
|
|||
void RTSPSource::finishDisconnectIfPossible() {
|
||||
if (mState != DISCONNECTED) {
|
||||
mHandler->disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
(new AMessage)->postReply(mDisconnectReplyID);
|
||||
|
|
|
@ -31,16 +31,28 @@ function load_ca(ca_name) {
|
|||
addCertFromFile(certdb, "test_ev_certs/" + ca_filename, 'CTu,CTu,CTu');
|
||||
}
|
||||
|
||||
var gHttpServer;
|
||||
var gOCSPResponseCounter = 0;
|
||||
const SERVER_PORT = 8888;
|
||||
|
||||
function start_ocsp_responder() {
|
||||
const SERVER_PORT = 8888;
|
||||
gHttpServer = new HttpServer();
|
||||
gHttpServer.registerPrefixHandler("/",
|
||||
function failingOCSPResponder() {
|
||||
let httpServer = new HttpServer();
|
||||
httpServer.registerPrefixHandler("/", function(request, response) {
|
||||
do_check_true(false);
|
||||
});
|
||||
httpServer.start(SERVER_PORT);
|
||||
return httpServer;
|
||||
}
|
||||
|
||||
function start_ocsp_responder(expectedCertNames) {
|
||||
let httpServer = new HttpServer();
|
||||
httpServer.registerPrefixHandler("/",
|
||||
function handleServerCallback(aRequest, aResponse) {
|
||||
do_check_neq(aRequest.host, "crl.example.com"); // No CRL checks
|
||||
let cert_nick = aRequest.path.slice(1, aRequest.path.length - 1);
|
||||
|
||||
do_check_true(expectedCertNames.length >= 1);
|
||||
let expected_nick = expectedCertNames.shift();
|
||||
do_check_eq(cert_nick, expected_nick);
|
||||
|
||||
do_print("Generating ocsp response for '" + cert_nick + "'");
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
|
||||
aResponse.setHeader("Content-Type", "application/ocsp-response");
|
||||
|
@ -54,11 +66,16 @@ function start_ocsp_responder() {
|
|||
let retArray = generateOCSPResponses(arg_array, "test_ev_certs");
|
||||
let responseBody = retArray[0];
|
||||
aResponse.bodyOutputStream.write(responseBody, responseBody.length);
|
||||
gOCSPResponseCounter++;
|
||||
});
|
||||
gHttpServer.identity.setPrimary("http", "www.example.com", SERVER_PORT);
|
||||
gHttpServer.identity.add("http", "crl.example.com", SERVER_PORT);
|
||||
gHttpServer.start(SERVER_PORT);
|
||||
httpServer.identity.setPrimary("http", "www.example.com", SERVER_PORT);
|
||||
httpServer.identity.add("http", "crl.example.com", SERVER_PORT);
|
||||
httpServer.start(SERVER_PORT);
|
||||
return {
|
||||
stop: function(callback) {
|
||||
do_check_eq(expectedCertNames.length, 0);
|
||||
httpServer.stop(callback);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function check_cert_err(cert_name, expected_error) {
|
||||
|
@ -97,44 +114,53 @@ function run_test() {
|
|||
Services.prefs.setCharPref("network.dns.localDomains",
|
||||
'www.example.com, crl.example.com');
|
||||
|
||||
start_ocsp_responder();
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
|
||||
add_test(function() {
|
||||
clearOCSPCache();
|
||||
let ocspResponder = start_ocsp_responder(["int-ev-valid", "ev-valid"]);
|
||||
check_ee_for_ev("ev-valid", true);
|
||||
run_next_test();
|
||||
ocspResponder.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function() {
|
||||
clearOCSPCache();
|
||||
let ocspResponder = start_ocsp_responder(["non-ev-root"]);
|
||||
check_ee_for_ev("non-ev-root", false);
|
||||
run_next_test();
|
||||
ocspResponder.stop(run_next_test);
|
||||
});
|
||||
|
||||
add_test(function() {
|
||||
clearOCSPCache();
|
||||
let ocspResponder = failingOCSPResponder();
|
||||
check_ee_for_ev("no-ocsp-url-cert", false);
|
||||
run_next_test();
|
||||
ocspResponder.stop(run_next_test);
|
||||
});
|
||||
|
||||
// Test for bug 917380
|
||||
add_test(function () {
|
||||
const nsIX509Cert = Ci.nsIX509Cert;
|
||||
// bug 917380: Chcek that an untrusted EV root is untrusted.
|
||||
const nsIX509Cert = Ci.nsIX509Cert;
|
||||
add_test(function() {
|
||||
let evRootCA = certdb.findCertByNickname(null, evrootnick);
|
||||
certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT, 0);
|
||||
|
||||
clearOCSPCache();
|
||||
let ocspResponder = failingOCSPResponder();
|
||||
check_cert_err("ev-valid", SEC_ERROR_UNTRUSTED_ISSUER);
|
||||
ocspResponder.stop(run_next_test);
|
||||
});
|
||||
|
||||
// bug 917380: Chcek that a trusted EV root is trusted.
|
||||
// TODO: isn't this a duplicate of the above test?
|
||||
add_test(function() {
|
||||
let evRootCA = certdb.findCertByNickname(null, evrootnick);
|
||||
certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT,
|
||||
Ci.nsIX509CertDB.TRUSTED_SSL |
|
||||
Ci.nsIX509CertDB.TRUSTED_EMAIL |
|
||||
Ci.nsIX509CertDB.TRUSTED_OBJSIGN);
|
||||
|
||||
clearOCSPCache();
|
||||
let ocspResponder = start_ocsp_responder(["int-ev-valid", "ev-valid"]);
|
||||
check_ee_for_ev("ev-valid", true);
|
||||
run_next_test();
|
||||
ocspResponder.stop(run_next_test);
|
||||
});
|
||||
|
||||
// The following test should be the last as it performs cleanups
|
||||
add_test(function() {
|
||||
do_check_eq(4, gOCSPResponseCounter);
|
||||
gHttpServer.stop(run_next_test);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
// 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";
|
||||
|
||||
// In which we connect to a server that staples an OCSP response for a
|
||||
// certificate signed by an intermediate that has an OCSP AIA to ensure
|
||||
// that an OCSP request is not made for the intermediate.
|
||||
|
||||
let gOCSPRequestCount = 0;
|
||||
|
||||
function add_ocsp_test(aHost, aExpectedResult) {
|
||||
add_connection_test(aHost, aExpectedResult,
|
||||
function() {
|
||||
clearOCSPCache();
|
||||
clearSessionCache();
|
||||
});
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
|
||||
|
||||
let ocspResponder = new HttpServer();
|
||||
ocspResponder.registerPrefixHandler("/", function(request, response) {
|
||||
gOCSPRequestCount++;
|
||||
response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
|
||||
let body = "Refusing to return a response";
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
});
|
||||
ocspResponder.start(8080);
|
||||
|
||||
add_tls_server_setup("OCSPStaplingServer");
|
||||
|
||||
add_ocsp_test("ocsp-stapling-with-intermediate.example.com", Cr.NS_OK);
|
||||
add_test(function() { ocspResponder.stop(run_next_test); });
|
||||
add_test(function() {
|
||||
do_check_eq(gOCSPRequestCount, 0);
|
||||
run_next_test();
|
||||
});
|
||||
run_next_test();
|
||||
}
|
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/cert8.db
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/cert8.db
Двоичный файл не отображается.
|
@ -35,6 +35,7 @@ const OCSPHost sOCSPHosts[] =
|
|||
{ "ocsp-stapling-trylater.example.com", ORTTryLater, nullptr },
|
||||
{ "ocsp-stapling-needssig.example.com", ORTNeedsSig, nullptr },
|
||||
{ "ocsp-stapling-unauthorized.example.com", ORTUnauthorized, nullptr },
|
||||
{ "ocsp-stapling-with-intermediate.example.com", ORTGood, "ocspEEWithIntermediate" },
|
||||
{ nullptr, ORTNull, nullptr }
|
||||
};
|
||||
|
||||
|
@ -52,9 +53,17 @@ DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
|
|||
fprintf(stderr, "found pre-defined host '%s'\n", host->mHostName);
|
||||
}
|
||||
|
||||
const char *certNickname;
|
||||
if (strcmp(host->mHostName,
|
||||
"ocsp-stapling-with-intermediate.example.com") == 0) {
|
||||
certNickname = host->mAdditionalCertName;
|
||||
} else {
|
||||
certNickname = DEFAULT_CERT_NICKNAME;
|
||||
}
|
||||
|
||||
ScopedCERTCertificate cert;
|
||||
SSLKEAType certKEA;
|
||||
if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, DEFAULT_CERT_NICKNAME,
|
||||
if (SECSuccess != ConfigSecureServerWithNamedCert(aFd, certNickname,
|
||||
&cert, &certKEA)) {
|
||||
return SSL_SNI_SEND_ALERT;
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -N -f $PASSWORD_FILE
|
|||
COMMON_ARGS="-v 360 -w -1 -2 -z $NOISE_FILE"
|
||||
|
||||
function make_CA {
|
||||
CA_RESPONSES="y\n0\ny"
|
||||
CA_RESPONSES="y\n1\ny"
|
||||
NICKNAME="${1}"
|
||||
SUBJECT="${2}"
|
||||
DERFILE="${3}"
|
||||
|
@ -74,7 +74,24 @@ function make_CA {
|
|||
|
||||
SERIALNO=1
|
||||
|
||||
function make_cert {
|
||||
function make_INT {
|
||||
INT_RESPONSES="y\n0\ny\n2\n7\nhttp://localhost:8080/\n\nn\nn\n"
|
||||
NICKNAME="${1}"
|
||||
SUBJECT="${2}"
|
||||
CA="${3}"
|
||||
|
||||
echo -e "$INT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $OUTPUT_DIR -S \
|
||||
-n $NICKNAME \
|
||||
-s "$SUBJECT" \
|
||||
-c $CA \
|
||||
-t ",," \
|
||||
-m $SERIALNO \
|
||||
--extAIA \
|
||||
$COMMON_ARGS
|
||||
SERIALNO=$(($SERIALNO + 1))
|
||||
}
|
||||
|
||||
function make_EE {
|
||||
CERT_RESPONSES="n\n\ny\n2\n7\nhttp://localhost:8080/\n\nn\nn\n"
|
||||
NICKNAME="${1}"
|
||||
SUBJECT="${2}"
|
||||
|
@ -98,10 +115,13 @@ function make_cert {
|
|||
|
||||
make_CA testCA 'CN=Test CA' test-ca.der
|
||||
make_CA otherCA 'CN=Other test CA' other-test-ca.der
|
||||
make_cert localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com"
|
||||
make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com"
|
||||
# A cert that is like localhostAndExampleCom, but with a different serial number for
|
||||
# testing the "OCSP response is from the right issuer, but it is for the wrong cert"
|
||||
# case.
|
||||
make_cert ocspOtherEndEntity 'CN=Other Cert' testCA "localhost,*.example.com"
|
||||
make_EE ocspOtherEndEntity 'CN=Other Cert' testCA "localhost,*.example.com"
|
||||
|
||||
make_INT testINT 'CN=Test Intermediate' testCA
|
||||
make_EE ocspEEWithIntermediate 'CN=Test End-entity with Intermediate' testINT "localhost,*.example.com"
|
||||
|
||||
cleanup
|
||||
|
|
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/key3.db
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/key3.db
Двоичный файл не отображается.
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
Двоичный файл не отображается.
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/secmod.db
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/secmod.db
Двоичный файл не отображается.
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/test-ca.der
Двоичные данные
security/manager/ssl/tests/unit/tlsserver/test-ca.der
Двоичный файл не отображается.
|
@ -37,6 +37,10 @@ fail-if = os == "android"
|
|||
run-sequentially = hardcoded ports
|
||||
# Bug 676972: test fails consistently on Android
|
||||
fail-if = os == "android"
|
||||
[test_ocsp_stapling_with_intermediate.js]
|
||||
run-sequentially = hardcoded ports
|
||||
# Bug 676972: test fails consistently on Android
|
||||
fail-if = os == "android"
|
||||
[test_ocsp_caching.js]
|
||||
run-sequentially = hardcoded ports
|
||||
# Bug 676972: test fails consistently on Android
|
||||
|
|
|
@ -10,4 +10,3 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -261,6 +261,28 @@ void ReleaseDPCache(CRLDPCache* dpcache, PRBool writeLocked);
|
|||
*/
|
||||
void CERT_MapStanError();
|
||||
|
||||
/* Like CERT_VerifyCert, except with an additional argument, flags. The
|
||||
* flags are defined immediately below.
|
||||
*
|
||||
* OCSP checking is always skipped when certUsage is certUsageStatusResponder.
|
||||
*/
|
||||
SECStatus
|
||||
cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
PRBool checkSig, SECCertUsage certUsage, PRTime t,
|
||||
PRUint32 flags, void *wincx, CERTVerifyLog *log);
|
||||
|
||||
/* Use the default settings.
|
||||
* cert_VerifyCertWithFlags(..., CERT_VERIFYCERT_USE_DEFAULTS) is equivalent
|
||||
* to CERT_VerifyCert(...);
|
||||
*/
|
||||
#define CERT_VERIFYCERT_USE_DEFAULTS 0
|
||||
|
||||
/* Skip all the OCSP checks during certificate verification, regardless of
|
||||
* the global OCSP settings. By default, certificate |cert| will have its
|
||||
* revocation status checked via OCSP according to the global OCSP settings.
|
||||
*/
|
||||
#define CERT_VERIFYCERT_SKIP_OCSP 1
|
||||
|
||||
/* Interface function for libpkix cert validation engine:
|
||||
* cert_verify wrapper. */
|
||||
SECStatus
|
||||
|
|
|
@ -1200,7 +1200,7 @@ CERT_VerifyCertificate(CERTCertDBHandle *handle, CERTCertificate *cert,
|
|||
|
||||
/*
|
||||
* Check OCSP revocation status, but only if the cert we are checking
|
||||
* is not a status reponder itself. We only do this in the case
|
||||
* is not a status responder itself. We only do this in the case
|
||||
* where we checked the cert chain (above); explicit trust "wins"
|
||||
* (avoids status checking, just as it avoids CRL checking) by
|
||||
* bypassing this code.
|
||||
|
@ -1234,11 +1234,20 @@ SECStatus
|
|||
CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
PRBool checkSig, SECCertUsage certUsage, PRTime t,
|
||||
void *wincx, CERTVerifyLog *log)
|
||||
{
|
||||
return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
|
||||
CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
PRBool checkSig, SECCertUsage certUsage, PRTime t,
|
||||
PRUint32 flags, void *wincx, CERTVerifyLog *log)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned int requiredKeyUsage;
|
||||
unsigned int requiredCertType;
|
||||
unsigned int flags;
|
||||
unsigned int failedFlags;
|
||||
unsigned int certType;
|
||||
PRBool trusted;
|
||||
PRBool allowOverride;
|
||||
|
@ -1307,10 +1316,10 @@ CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
|
|||
LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType);
|
||||
}
|
||||
|
||||
rv = cert_CheckLeafTrust(cert,certUsage, &flags, &trusted);
|
||||
rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
|
||||
if (rv == SECFailure) {
|
||||
PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
|
||||
LOG_ERROR_OR_EXIT(log,cert,0,flags);
|
||||
LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
|
||||
} else if (trusted) {
|
||||
goto done;
|
||||
}
|
||||
|
@ -1323,15 +1332,17 @@ CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
|
|||
}
|
||||
|
||||
/*
|
||||
* Check revocation status, but only if the cert we are checking
|
||||
* is not a status reponder itself. We only do this in the case
|
||||
* where we checked the cert chain (above); explicit trust "wins"
|
||||
* (avoids status checking, just as it avoids CRL checking, which
|
||||
* is all done inside VerifyCertChain) by bypassing this code.
|
||||
* Check revocation status, but only if the cert we are checking is not a
|
||||
* status responder itself and the caller did not ask us to skip the check.
|
||||
* We only do this in the case where we checked the cert chain (above);
|
||||
* explicit trust "wins" (avoids status checking, just as it avoids CRL
|
||||
* checking, which is all done inside VerifyCertChain) by bypassing this
|
||||
* code.
|
||||
*/
|
||||
statusConfig = CERT_GetStatusConfig(handle);
|
||||
if (certUsage != certUsageStatusResponder && statusConfig != NULL) {
|
||||
if (statusConfig->statusChecker != NULL) {
|
||||
if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
|
||||
certUsage != certUsageStatusResponder) {
|
||||
statusConfig = CERT_GetStatusConfig(handle);
|
||||
if (statusConfig && statusConfig->statusChecker) {
|
||||
rv = (* statusConfig->statusChecker)(handle, cert,
|
||||
t, wincx);
|
||||
if (rv != SECSuccess) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "secasn1.h"
|
||||
#include "secder.h"
|
||||
#include "cert.h"
|
||||
#include "certi.h"
|
||||
#include "xconst.h"
|
||||
#include "secerr.h"
|
||||
#include "secoid.h"
|
||||
|
@ -4184,8 +4185,9 @@ CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,
|
|||
} else {
|
||||
certUsage = certUsageStatusResponder;
|
||||
}
|
||||
rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
|
||||
certUsage, producedAt, pwArg, NULL);
|
||||
rv = cert_VerifyCertWithFlags(handle, signerCert, PR_TRUE, certUsage,
|
||||
producedAt, CERT_VERIFYCERT_SKIP_OCSP,
|
||||
pwArg, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
|
||||
goto finish;
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
This directory contains patches that were added locally
|
||||
on top of the NSS release.
|
||||
|
||||
bug-950129.patch Make OCSP fetching policy for OCSP response signing
|
||||
certificates consistent.
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
# HG changeset patch
|
||||
# Parent 352d188c67d9fefd82524c4439a5d04679687945
|
||||
# User Brian Smith <brian@briansmith.org>
|
||||
diff --git a/security/nss/lib/certdb/certi.h b/security/nss/lib/certdb/certi.h
|
||||
--- a/security/nss/lib/certdb/certi.h
|
||||
+++ b/security/nss/lib/certdb/certi.h
|
||||
@@ -256,16 +256,38 @@ void ReleaseDPCache(CRLDPCache* dpcache,
|
||||
|
||||
/*
|
||||
* map Stan errors into NSS errors
|
||||
* This function examines the stan error stack and automatically sets
|
||||
* PORT_SetError(); to the appropriate SEC_ERROR value.
|
||||
*/
|
||||
void CERT_MapStanError();
|
||||
|
||||
+/* Like CERT_VerifyCert, except with an additional argument, flags. The
|
||||
+ * flags are defined immediately below.
|
||||
+ *
|
||||
+ * OCSP checking is always skipped when certUsage is certUsageStatusResponder.
|
||||
+ */
|
||||
+SECStatus
|
||||
+cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
+ PRBool checkSig, SECCertUsage certUsage, PRTime t,
|
||||
+ PRUint32 flags, void *wincx, CERTVerifyLog *log);
|
||||
+
|
||||
+/* Use the default settings.
|
||||
+ * cert_VerifyCertWithFlags(..., CERT_VERIFYCERT_USE_DEFAULTS) is equivalent
|
||||
+ * to CERT_VerifyCert(...);
|
||||
+ */
|
||||
+#define CERT_VERIFYCERT_USE_DEFAULTS 0
|
||||
+
|
||||
+/* Skip all the OCSP checks during certificate verification, regardless of
|
||||
+ * the global OCSP settings. By default, certificate |cert| will have its
|
||||
+ * revocation status checked via OCSP according to the global OCSP settings.
|
||||
+ */
|
||||
+#define CERT_VERIFYCERT_SKIP_OCSP 1
|
||||
+
|
||||
/* Interface function for libpkix cert validation engine:
|
||||
* cert_verify wrapper. */
|
||||
SECStatus
|
||||
cert_VerifyCertChainPkix(CERTCertificate *cert,
|
||||
PRBool checkSig,
|
||||
SECCertUsage requiredUsage,
|
||||
PRTime time,
|
||||
void *wincx,
|
||||
diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c
|
||||
--- a/security/nss/lib/certhigh/certvfy.c
|
||||
+++ b/security/nss/lib/certhigh/certvfy.c
|
||||
@@ -1195,17 +1195,17 @@ CERT_VerifyCertificate(CERTCertDBHandle
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
/* EXIT_IF_NOT_LOGGING(log); XXX ???? */
|
||||
INVALID_USAGE();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check OCSP revocation status, but only if the cert we are checking
|
||||
- * is not a status reponder itself. We only do this in the case
|
||||
+ * is not a status responder itself. We only do this in the case
|
||||
* where we checked the cert chain (above); explicit trust "wins"
|
||||
* (avoids status checking, just as it avoids CRL checking) by
|
||||
* bypassing this code.
|
||||
*/
|
||||
|
||||
if (PR_FALSE == checkedOCSP) {
|
||||
checkedOCSP = PR_TRUE; /* only check OCSP once */
|
||||
statusConfig = CERT_GetStatusConfig(handle);
|
||||
@@ -1230,20 +1230,29 @@ loser:
|
||||
return(valid);
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
PRBool checkSig, SECCertUsage certUsage, PRTime t,
|
||||
void *wincx, CERTVerifyLog *log)
|
||||
{
|
||||
+ return cert_VerifyCertWithFlags(handle, cert, checkSig, certUsage, t,
|
||||
+ CERT_VERIFYCERT_USE_DEFAULTS, wincx, log);
|
||||
+}
|
||||
+
|
||||
+SECStatus
|
||||
+cert_VerifyCertWithFlags(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
+ PRBool checkSig, SECCertUsage certUsage, PRTime t,
|
||||
+ PRUint32 flags, void *wincx, CERTVerifyLog *log)
|
||||
+{
|
||||
SECStatus rv;
|
||||
unsigned int requiredKeyUsage;
|
||||
unsigned int requiredCertType;
|
||||
- unsigned int flags;
|
||||
+ unsigned int failedFlags;
|
||||
unsigned int certType;
|
||||
PRBool trusted;
|
||||
PRBool allowOverride;
|
||||
SECCertTimeValidity validity;
|
||||
CERTStatusConfig *statusConfig;
|
||||
|
||||
#ifdef notdef
|
||||
/* check if this cert is in the Evil list */
|
||||
@@ -1302,41 +1311,43 @@ CERT_VerifyCert(CERTCertDBHandle *handle
|
||||
PORT_SetError(SEC_ERROR_INADEQUATE_KEY_USAGE);
|
||||
LOG_ERROR_OR_EXIT(log,cert,0,requiredKeyUsage);
|
||||
}
|
||||
if ( !( certType & requiredCertType ) ) {
|
||||
PORT_SetError(SEC_ERROR_INADEQUATE_CERT_TYPE);
|
||||
LOG_ERROR_OR_EXIT(log,cert,0,requiredCertType);
|
||||
}
|
||||
|
||||
- rv = cert_CheckLeafTrust(cert,certUsage, &flags, &trusted);
|
||||
+ rv = cert_CheckLeafTrust(cert, certUsage, &failedFlags, &trusted);
|
||||
if (rv == SECFailure) {
|
||||
PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
|
||||
- LOG_ERROR_OR_EXIT(log,cert,0,flags);
|
||||
+ LOG_ERROR_OR_EXIT(log, cert, 0, failedFlags);
|
||||
} else if (trusted) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
rv = CERT_VerifyCertChain(handle, cert, checkSig, certUsage,
|
||||
t, wincx, log);
|
||||
if (rv != SECSuccess) {
|
||||
EXIT_IF_NOT_LOGGING(log);
|
||||
}
|
||||
|
||||
/*
|
||||
- * Check revocation status, but only if the cert we are checking
|
||||
- * is not a status reponder itself. We only do this in the case
|
||||
- * where we checked the cert chain (above); explicit trust "wins"
|
||||
- * (avoids status checking, just as it avoids CRL checking, which
|
||||
- * is all done inside VerifyCertChain) by bypassing this code.
|
||||
+ * Check revocation status, but only if the cert we are checking is not a
|
||||
+ * status responder itself and the caller did not ask us to skip the check.
|
||||
+ * We only do this in the case where we checked the cert chain (above);
|
||||
+ * explicit trust "wins" (avoids status checking, just as it avoids CRL
|
||||
+ * checking, which is all done inside VerifyCertChain) by bypassing this
|
||||
+ * code.
|
||||
*/
|
||||
- statusConfig = CERT_GetStatusConfig(handle);
|
||||
- if (certUsage != certUsageStatusResponder && statusConfig != NULL) {
|
||||
- if (statusConfig->statusChecker != NULL) {
|
||||
+ if (!(flags & CERT_VERIFYCERT_SKIP_OCSP) &&
|
||||
+ certUsage != certUsageStatusResponder) {
|
||||
+ statusConfig = CERT_GetStatusConfig(handle);
|
||||
+ if (statusConfig && statusConfig->statusChecker) {
|
||||
rv = (* statusConfig->statusChecker)(handle, cert,
|
||||
t, wincx);
|
||||
if (rv != SECSuccess) {
|
||||
LOG_ERROR_OR_EXIT(log,cert,0,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c
|
||||
--- a/security/nss/lib/certhigh/ocsp.c
|
||||
+++ b/security/nss/lib/certhigh/ocsp.c
|
||||
@@ -13,16 +13,17 @@
|
||||
#include "prnetdb.h"
|
||||
|
||||
#include "seccomon.h"
|
||||
#include "secitem.h"
|
||||
#include "secoidt.h"
|
||||
#include "secasn1.h"
|
||||
#include "secder.h"
|
||||
#include "cert.h"
|
||||
+#include "certi.h"
|
||||
#include "xconst.h"
|
||||
#include "secerr.h"
|
||||
#include "secoid.h"
|
||||
#include "hasht.h"
|
||||
#include "sechash.h"
|
||||
#include "secasn1.h"
|
||||
#include "plbase64.h"
|
||||
#include "keyhi.h"
|
||||
@@ -4179,18 +4180,19 @@ CERT_VerifyOCSPResponseSignature(CERTOCS
|
||||
rv = SECSuccess;
|
||||
} else {
|
||||
SECCertUsage certUsage;
|
||||
if (CERT_IsCACert(signerCert, NULL)) {
|
||||
certUsage = certUsageAnyCA;
|
||||
} else {
|
||||
certUsage = certUsageStatusResponder;
|
||||
}
|
||||
- rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
|
||||
- certUsage, producedAt, pwArg, NULL);
|
||||
+ rv = cert_VerifyCertWithFlags(handle, signerCert, PR_TRUE, certUsage,
|
||||
+ producedAt, CERT_VERIFYCERT_SKIP_OCSP,
|
||||
+ pwArg, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
rv = ocsp_VerifyResponseSignature(signerCert, signature,
|
||||
tbsResponseDataDER,
|
|
@ -676,7 +676,6 @@
|
|||
"layout/generic/test/test_plugin_clipping.xhtml": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"layout/generic/test/test_plugin_clipping2.xhtml": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"layout/generic/test/test_plugin_clipping_table.xhtml": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"layout/generic/test/test_plugin_clipping_transformed.xhtml": "Bug 931116, b2g desktop specific, initial triage",
|
||||
"toolkit/devtools/apps/tests/test_webapps_actor.html": "Bug 931116, b2g desktop specific, initial triage"
|
||||
"layout/generic/test/test_plugin_clipping_transformed.xhtml": "Bug 931116, b2g desktop specific, initial triage"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@
|
|||
"content/events/test/test_bug574663.html":"",
|
||||
"content/events/test/test_bug607464.html":"",
|
||||
"content/events/test/test_wheel_default_action.html":"",
|
||||
"content/base/test/test_bug682592.html":"",
|
||||
"content/base/test/test_bug682592.html":"",
|
||||
"content/html/document/test/test_bug369370.html":"",
|
||||
"content/svg/content/test/test_text_selection.html":"Mouse selection not workin on b2g",
|
||||
"content/svg/content/test/test_SVGAnimatedImageSMILDisabled.html":"",
|
||||
|
@ -260,8 +260,9 @@
|
|||
"docshell/test/navigation/test_reserved.html":"",
|
||||
"docshell/test/test_bug413310.html":"",
|
||||
|
||||
"dom/imptests/html/webgl":"",
|
||||
"dom/imptests/html/webgl":"",
|
||||
"dom/battery/test/test_battery_basics.html":"",
|
||||
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_Alert.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_AppFramePermission.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_AppWindowNamespace.html":"",
|
||||
|
@ -269,7 +270,32 @@
|
|||
"dom/browser-element/mochitest/test_browserElement_inproc_BrowserWindowNamespace.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_CloseApp.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_CloseFromOpener.html":"",
|
||||
"dom/browser-element/":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_ErrorSecurity.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_FrameWrongURI.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_KeyEvents.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_OpenMixedProcess.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_OpenNamed.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_OpenWindow.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowDifferentOrigin.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowInFrame.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_OpenWindowRejected.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_SecurityChange.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_inproc_TargetBlank.html":"",
|
||||
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_AppFramePermission.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_AppWindowNamespace.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_Auth.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_BrowserWindowNamespace.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_ErrorSecurity.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_FrameWrongURI.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_OpenMixedProcess.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_OpenNamed.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_OpenWindow.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_OpenWindowDifferentOrigin.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_OpenWindowInFrame.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_OpenWindowRejected.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_SecurityChange.html":"",
|
||||
"dom/browser-element/mochitest/test_browserElement_oop_TargetBlank.html":"",
|
||||
|
||||
"dom/file/test/test_progress_events.html":"All of these fail fairly regularly with: UnknownError: The operation failed for reasons unrelated to the database itself and not covered by any other error code. at http://mochi.test:8888/tests/dom/file/test/helpers.js:126",
|
||||
"dom/file/test/test_request_readyState.html":"",
|
||||
|
|
|
@ -154,3 +154,7 @@ user_pref("browser.pagethumbnails.capturing_disabled", true);
|
|||
// Indicate that the download panel has been shown once so that whichever
|
||||
// download test runs first doesn't show the popup inconsistently.
|
||||
user_pref("browser.download.panel.shown", true);
|
||||
|
||||
// prefs for firefox metro.
|
||||
// Disable first-tun tab
|
||||
user_pref("browser.firstrun.count", 0);
|
||||
|
|
|
@ -37,6 +37,8 @@ add_task(function() {
|
|||
do_check_true(!!OS.Constants.Path.desktopDir);
|
||||
do_check_eq(OS.Constants.Path.desktopDir, Services.dirsvc.get("Desk", Components.interfaces.nsIFile).path);
|
||||
|
||||
compare_paths(OS.Constants.Path.userApplicationDataDir, "UAppData");
|
||||
|
||||
compare_paths(OS.Constants.Path.winAppDataDir, "AppData");
|
||||
compare_paths(OS.Constants.Path.winStartMenuProgsDir, "Progs");
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ let loaderGlobals = {
|
|||
btoa: btoa,
|
||||
console: console,
|
||||
_Iterator: Iterator,
|
||||
ChromeWorker: ChromeWorker,
|
||||
loader: {
|
||||
lazyGetter: XPCOMUtils.defineLazyGetter.bind(XPCOMUtils),
|
||||
lazyImporter: XPCOMUtils.defineLazyModuleGetter.bind(XPCOMUtils),
|
||||
|
@ -43,7 +44,8 @@ let loaderGlobals = {
|
|||
};
|
||||
|
||||
// Used when the tools should be loaded from the Firefox package itself (the default)
|
||||
var BuiltinProvider = {
|
||||
function BuiltinProvider() {}
|
||||
BuiltinProvider.prototype = {
|
||||
load: function() {
|
||||
this.loader = new loader.Loader({
|
||||
modules: {
|
||||
|
@ -72,7 +74,8 @@ var BuiltinProvider = {
|
|||
// Allow access to xpcshell test items from the loader.
|
||||
"xpcshell-test": "resource://test"
|
||||
},
|
||||
globals: loaderGlobals
|
||||
globals: loaderGlobals,
|
||||
invisibleToDebugger: this.invisibleToDebugger
|
||||
});
|
||||
|
||||
return promise.resolve(undefined);
|
||||
|
@ -87,7 +90,8 @@ var BuiltinProvider = {
|
|||
// Used when the tools should be loaded from a mozilla-central checkout. In addition
|
||||
// to different paths, it needs to write chrome.manifest files to override chrome urls
|
||||
// from the builtin tools.
|
||||
var SrcdirProvider = {
|
||||
function SrcdirProvider() {}
|
||||
SrcdirProvider.prototype = {
|
||||
fileURI: function(path) {
|
||||
let file = new FileUtils.File(path);
|
||||
return Services.io.newFileURI(file).spec;
|
||||
|
@ -134,7 +138,8 @@ var SrcdirProvider = {
|
|||
"acorn": acornURI,
|
||||
"acorn_loose": acornLoosseURI
|
||||
},
|
||||
globals: loaderGlobals
|
||||
globals: loaderGlobals,
|
||||
invisibleToDebugger: this.invisibleToDebugger
|
||||
});
|
||||
|
||||
return this._writeManifest(devtoolsDir).then(null, Cu.reportError);
|
||||
|
@ -218,12 +223,29 @@ var SrcdirProvider = {
|
|||
* then a new one can also be created.
|
||||
*/
|
||||
this.DevToolsLoader = function DevToolsLoader() {
|
||||
this._chooseProvider();
|
||||
this.require = this.require.bind(this);
|
||||
};
|
||||
|
||||
DevToolsLoader.prototype = {
|
||||
get provider() {
|
||||
if (!this._provider) {
|
||||
this._chooseProvider();
|
||||
}
|
||||
return this._provider;
|
||||
},
|
||||
|
||||
_provider: null,
|
||||
|
||||
/**
|
||||
* A dummy version of require, in case a provider hasn't been chosen yet when
|
||||
* this is first called. This will then be replaced by the real version.
|
||||
* @see setProvider
|
||||
*/
|
||||
require: function() {
|
||||
this._chooseProvider();
|
||||
return this.require.apply(this, arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a URI to the loader.
|
||||
* @param string id
|
||||
|
@ -234,7 +256,7 @@ DevToolsLoader.prototype = {
|
|||
*/
|
||||
loadURI: function(id, uri) {
|
||||
let module = loader.Module(id, uri);
|
||||
return loader.load(this._provider.loader, module).exports;
|
||||
return loader.load(this.provider.loader, module).exports;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -248,7 +270,7 @@ DevToolsLoader.prototype = {
|
|||
*/
|
||||
main: function(id) {
|
||||
this._mainid = id;
|
||||
this._main = loader.main(this._provider.loader, id);
|
||||
this._main = loader.main(this.provider.loader, id);
|
||||
|
||||
// Mirror the main module's exports on this object.
|
||||
Object.getOwnPropertyNames(this._main).forEach(key => {
|
||||
|
@ -271,6 +293,7 @@ DevToolsLoader.prototype = {
|
|||
this._provider.unload("newprovider");
|
||||
}
|
||||
this._provider = provider;
|
||||
this._provider.invisibleToDebugger = this.invisibleToDebugger;
|
||||
this._provider.load();
|
||||
this.require = loader.Require(this._provider.loader, { id: "devtools" });
|
||||
|
||||
|
@ -284,9 +307,9 @@ DevToolsLoader.prototype = {
|
|||
*/
|
||||
_chooseProvider: function() {
|
||||
if (Services.prefs.prefHasUserValue("devtools.loader.srcdir")) {
|
||||
this.setProvider(SrcdirProvider);
|
||||
this.setProvider(new SrcdirProvider());
|
||||
} else {
|
||||
this.setProvider(BuiltinProvider);
|
||||
this.setProvider(new BuiltinProvider());
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -302,6 +325,17 @@ DevToolsLoader.prototype = {
|
|||
delete this._provider;
|
||||
this._chooseProvider();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets whether the compartments loaded by this instance should be invisible
|
||||
* to the debugger. Invisibility is needed for loaders that support debugging
|
||||
* of chrome code. This is true of remote target environments, like Fennec or
|
||||
* B2G. It is not the default case for desktop Firefox because we offer the
|
||||
* Browser Toolbox for chrome debugging there, which uses its own, separate
|
||||
* loader instance.
|
||||
* @see browser/devtools/framework/ToolboxProcess.jsm
|
||||
*/
|
||||
invisibleToDebugger: Services.appinfo.name !== "Firefox"
|
||||
};
|
||||
|
||||
// Export the standard instance of DevToolsLoader used by the tools.
|
||||
|
|
|
@ -14,20 +14,36 @@ const { Services } = Cu.import("resource://gre/modules/Services.jsm");
|
|||
let gClient, gActor;
|
||||
|
||||
function connect(onDone) {
|
||||
// Initialize a loopback remote protocol connection
|
||||
DebuggerServer.init(function () { return true; });
|
||||
// We need to register browser actors to have `listTabs` working
|
||||
// and also have a root actor
|
||||
|
||||
if (Services.appinfo.name == "B2G") {
|
||||
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webbrowser.js");
|
||||
DebuggerServer.addActors('chrome://browser/content/dbg-browser-actors.js');
|
||||
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webapps.js");
|
||||
} else {
|
||||
// On b2g, we try to exercice the code that launches the production debugger server
|
||||
let settingsService = Cc["@mozilla.org/settingsService;1"].getService(Ci.nsISettingsService);
|
||||
settingsService.createLock().set("devtools.debugger.remote-enabled", true, null);
|
||||
// We can't use `set` callback as it is fired before shell.js code listening for this setting
|
||||
// is actually called. Same thing applies to mozsettings-changed obs notification.
|
||||
// So listen to a custom event until bug 942756 lands
|
||||
let observer = {
|
||||
observe: function (subject, topic, data) {
|
||||
Services.obs.removeObserver(observer, "debugger-server-started");
|
||||
let transport = debuggerSocketConnect("127.0.0.1", 6000);
|
||||
startClient(transport, onDone);
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(observer, "debugger-server-started", false);
|
||||
} else {
|
||||
// Initialize a loopback remote protocol connection
|
||||
DebuggerServer.init(function () { return true; });
|
||||
// We need to register browser actors to have `listTabs` working
|
||||
// and also have a root actor
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
startClient(transport, onDone);
|
||||
}
|
||||
}
|
||||
|
||||
function startClient(transport, onDone) {
|
||||
// Setup client and actor used in all tests
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient = new DebuggerClient(transport);
|
||||
gClient.connect(function onConnect() {
|
||||
gClient.listTabs(function onListTabs(aResponse) {
|
||||
gActor = aResponse.webappsActor;
|
||||
|
|
|
@ -75,7 +75,9 @@ var steps = [
|
|||
SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.mozBrowserFramesEnabled", true],
|
||||
["security.apps.privileged.CSP.default",
|
||||
"default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"]
|
||||
"default-src *; script-src 'self'; object-src 'none'; style-src 'self' 'unsafe-inline'"],
|
||||
["devtools.debugger.unix-domain-socket", 6000],
|
||||
["devtools.debugger.prompt-connection", false]
|
||||
]
|
||||
}, next);
|
||||
},
|
||||
|
|
|
@ -5,10 +5,16 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
var Cu = Components.utils;
|
||||
var Cr = Components.results;
|
||||
// On B2G scope object misbehaves and we have to bind globals to `this`
|
||||
// in order to ensure theses variable to be visible in transport.js
|
||||
this.Ci = Ci;
|
||||
this.Cc = Cc;
|
||||
this.Cu = Cu;
|
||||
this.Cr = Cr;
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DebuggerTransport",
|
||||
"DebuggerClient",
|
||||
|
|
|
@ -15,31 +15,11 @@ const Ci = Components.interfaces;
|
|||
const Cc = Components.classes;
|
||||
const Cu = Components.utils;
|
||||
|
||||
const { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["DebuggerServer", "ActorPool"];
|
||||
|
||||
var loadSubScript =
|
||||
"function loadSubScript(aURL)\n" +
|
||||
"{\n" +
|
||||
"const Ci = Components.interfaces;\n" +
|
||||
"const Cc = Components.classes;\n" +
|
||||
" try {\n" +
|
||||
" let loader = Cc[\"@mozilla.org/moz/jssubscript-loader;1\"]\n" +
|
||||
" .getService(Ci.mozIJSSubScriptLoader);\n" +
|
||||
" loader.loadSubScript(aURL, this);\n" +
|
||||
" } catch(e) {\n" +
|
||||
" dump(\"Error loading: \" + aURL + \": \" + e + \" - \" + e.stack + \"\\n\");\n" +
|
||||
" throw e;\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
let server = devtools.require("devtools/server/main");
|
||||
|
||||
// Load the debugging server in a sandbox with its own compartment.
|
||||
var systemPrincipal = Cc["@mozilla.org/systemprincipal;1"]
|
||||
.createInstance(Ci.nsIPrincipal);
|
||||
|
||||
var gGlobal = Cu.Sandbox(systemPrincipal);
|
||||
gGlobal.ChromeWorker = ChromeWorker;
|
||||
Cu.evalInSandbox(loadSubScript, gGlobal, "1.8");
|
||||
gGlobal.loadSubScript("resource://gre/modules/devtools/server/main.js");
|
||||
|
||||
this.DebuggerServer = gGlobal.DebuggerServer;
|
||||
this.ActorPool = gGlobal.ActorPool;
|
||||
this.DebuggerServer = server.DebuggerServer;
|
||||
this.ActorPool = server.ActorPool;
|
||||
|
|
|
@ -10,36 +10,22 @@
|
|||
* debugging global.
|
||||
*/
|
||||
|
||||
// |this.require| is used to test if this file was loaded via the devtools
|
||||
// loader (as it is in DebuggerProcess.jsm) or via loadSubScript (as it is from
|
||||
// dbg-server.jsm). Note that testing |require| is not safe in either
|
||||
// situation, as it causes a ReferenceError.
|
||||
var Ci, Cc, CC, Cu, Cr, Components;
|
||||
if (this.require) {
|
||||
({ Ci, Cc, CC, Cu, Cr, components: Components }) = require("chrome");
|
||||
} else {
|
||||
({
|
||||
interfaces: Ci,
|
||||
classes: Cc,
|
||||
Constructor: CC,
|
||||
utils: Cu,
|
||||
results: Cr
|
||||
}) = Components;
|
||||
}
|
||||
|
||||
// On B2G, if |this.require| is undefined at this point, it remains undefined
|
||||
// later on when |DebuggerServer.registerModule| is called. On desktop (and
|
||||
// perhaps other places), if |this.require| starts out undefined, it ends up
|
||||
// being set to some native code by the time we get to |registerModule|. Here
|
||||
// we perform a test early on, and then cache the correct require function for
|
||||
// later use.
|
||||
var localRequire;
|
||||
if (this.require) {
|
||||
localRequire = id => require(id);
|
||||
} else {
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
localRequire = id => devtools.require(id);
|
||||
}
|
||||
// Until all Debugger server code is converted to SDK modules,
|
||||
// imports Components.* alias from chrome module.
|
||||
var { Ci, Cc, CC, Cu, Cr } = require("chrome");
|
||||
// On B2G, `this` != Global scope, so `Ci` won't be binded on `this`
|
||||
// (i.e. this.Ci is undefined) Then later, when using loadSubScript,
|
||||
// Ci,... won't be defined for sub scripts.
|
||||
this.Ci = Ci;
|
||||
this.Cc = Cc;
|
||||
this.CC = CC;
|
||||
this.Cu = Cu;
|
||||
this.Cr = Cr;
|
||||
// Overload `Components` to prevent SDK loader exception on Components
|
||||
// object usage
|
||||
Object.defineProperty(this, "Components", {
|
||||
get: function () require("chrome").components
|
||||
});
|
||||
|
||||
const DBG_STRINGS_URI = "chrome://global/locale/devtools/debugger.properties";
|
||||
|
||||
|
@ -49,7 +35,6 @@ Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm");
|
|||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
let wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
const promptConnections = Services.prefs.getBoolPref("devtools.debugger.prompt-connection");
|
||||
|
||||
Cu.import("resource://gre/modules/jsdebugger.jsm");
|
||||
addDebuggerToGlobal(this);
|
||||
|
@ -68,10 +53,12 @@ function loadSubScript(aURL)
|
|||
}
|
||||
}
|
||||
|
||||
let loaderRequire = this.require;
|
||||
this.require = null;
|
||||
loadSubScript.call(this, "resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
this.require = loaderRequire;
|
||||
let {defer, resolve, reject, promised, all} = require("sdk/core/promise");
|
||||
this.defer = defer;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
this.promised = promised;
|
||||
this.all = all;
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
|
||||
|
||||
|
@ -82,12 +69,14 @@ function dumpn(str) {
|
|||
dump("DBG-SERVER: " + str + "\n");
|
||||
}
|
||||
}
|
||||
this.dumpn = dumpn;
|
||||
|
||||
function dbg_assert(cond, e) {
|
||||
if (!cond) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
this.dbg_assert = dbg_assert;
|
||||
|
||||
loadSubScript.call(this, "resource://gre/modules/devtools/server/transport.js");
|
||||
|
||||
|
@ -324,7 +313,7 @@ var DebuggerServer = {
|
|||
}
|
||||
|
||||
let moduleAPI = ModuleAPI();
|
||||
let mod = localRequire(id);
|
||||
let mod = require(id);
|
||||
mod.register(moduleAPI);
|
||||
gRegisteredModules[id] = { module: mod, api: moduleAPI };
|
||||
},
|
||||
|
@ -523,7 +512,7 @@ var DebuggerServer = {
|
|||
|
||||
onSocketAccepted:
|
||||
makeInfallible(function DS_onSocketAccepted(aSocket, aTransport) {
|
||||
if (promptConnections && !this._allowConnection()) {
|
||||
if (Services.prefs.getBoolPref("devtools.debugger.prompt-connection") && !this._allowConnection()) {
|
||||
return;
|
||||
}
|
||||
dumpn("New debugging connection on " + aTransport.host + ":" + aTransport.port);
|
||||
|
@ -690,6 +679,8 @@ var DebuggerServer = {
|
|||
if (this.exports) {
|
||||
exports.DebuggerServer = DebuggerServer;
|
||||
}
|
||||
// Needed on B2G (See header note)
|
||||
this.DebuggerServer = DebuggerServer;
|
||||
|
||||
/**
|
||||
* Construct an ActorPool.
|
||||
|
@ -708,6 +699,8 @@ function ActorPool(aConnection)
|
|||
if (this.exports) {
|
||||
exports.ActorPool = ActorPool;
|
||||
}
|
||||
// Needed on B2G (See header note)
|
||||
this.ActorPool = ActorPool;
|
||||
|
||||
ActorPool.prototype = {
|
||||
/**
|
||||
|
|
|
@ -37,11 +37,13 @@
|
|||
const { BuiltinProvider, SrcdirProvider } =
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
|
||||
BuiltinProvider.load();
|
||||
SrcdirProvider.load();
|
||||
let builtin = new BuiltinProvider();
|
||||
builtin.load();
|
||||
let srcdir = new SrcdirProvider();
|
||||
srcdir.load();
|
||||
|
||||
is(BuiltinProvider.loader.mapping.length,
|
||||
SrcdirProvider.loader.mapping.length + 1,
|
||||
is(builtin.loader.mapping.length,
|
||||
srcdir.loader.mapping.length + 1,
|
||||
"The built-in loader should have only one more mapping for testing.");
|
||||
|
||||
Services.prefs.clearUserPref(SRCDIR_PREF);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { DevToolsLoader } =
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
|
||||
/**
|
||||
* Ensure that each instance of the Dev Tools loader contains its own loader
|
||||
* instance, and also returns unique objects. This ensures there is no sharing
|
||||
* in place between loaders.
|
||||
*/
|
||||
function run_test() {
|
||||
let loader1 = new DevToolsLoader();
|
||||
let loader2 = new DevToolsLoader();
|
||||
|
||||
let color1 = loader1.require("devtools/css-color");
|
||||
let color2 = loader2.require("devtools/css-color");
|
||||
|
||||
do_check_true(color1 !== color2);
|
||||
|
||||
do_check_true(loader1._provider !== loader2._provider);
|
||||
do_check_true(loader1._provider.loader !== loader2._provider.loader);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const { DevToolsLoader } =
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
Cu.import("resource://gre/modules/jsdebugger.jsm");
|
||||
addDebuggerToGlobal(this);
|
||||
|
||||
const COLOR_URI = "resource://gre/modules/devtools/css-color.js";
|
||||
|
||||
/**
|
||||
* Ensure that sandboxes created via the Dev Tools loader respect the
|
||||
* invisibleToDebugger flag.
|
||||
*/
|
||||
function run_test() {
|
||||
visible_loader();
|
||||
invisible_loader();
|
||||
}
|
||||
|
||||
function visible_loader() {
|
||||
let loader = new DevToolsLoader();
|
||||
loader.invisibleToDebugger = false;
|
||||
loader.require("devtools/css-color");
|
||||
|
||||
let dbg = new Debugger();
|
||||
let sandbox = loader._provider.loader.sandboxes[COLOR_URI];
|
||||
|
||||
try {
|
||||
dbg.addDebuggee(sandbox);
|
||||
do_check_true(true);
|
||||
} catch(e) {
|
||||
do_throw("debugger could not add visible value");
|
||||
}
|
||||
}
|
||||
|
||||
function invisible_loader() {
|
||||
let loader = new DevToolsLoader();
|
||||
loader.invisibleToDebugger = true;
|
||||
loader.require("devtools/css-color");
|
||||
|
||||
let dbg = new Debugger();
|
||||
let sandbox = loader._provider.loader.sandboxes[COLOR_URI];
|
||||
|
||||
try {
|
||||
dbg.addDebuggee(sandbox);
|
||||
do_throw("debugger added invisible value");
|
||||
} catch(e) {
|
||||
do_check_true(true);
|
||||
}
|
||||
}
|
|
@ -2,5 +2,7 @@
|
|||
head = head_devtools.js
|
||||
tail =
|
||||
|
||||
[test_independent_loaders.js]
|
||||
[test_invisible_loader.js]
|
||||
[test_safeErrorString.js]
|
||||
[test_defineLazyPrototypeGetter.js]
|
||||
|
|
|
@ -606,9 +606,12 @@ GetOSApplyToDir(nsACString& applyToDir)
|
|||
NS_ASSERTION(ds, "Can't get directory service");
|
||||
|
||||
nsCOMPtr<nsIFile> osApplyToDir;
|
||||
DebugOnly<nsresult> rv = ds->Get(XRE_OS_UPDATE_APPLY_TO_DIR, NS_GET_IID(nsIFile),
|
||||
nsresult rv = ds->Get(XRE_OS_UPDATE_APPLY_TO_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(osApplyToDir));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't get the OS applyTo dir");
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Can't get the OS applyTo dir"));
|
||||
return rv;
|
||||
}
|
||||
|
||||
return osApplyToDir->GetNativePath(applyToDir);
|
||||
}
|
||||
|
@ -1115,14 +1118,20 @@ nsUpdateProcessor::ProcessUpdate(nsIUpdate* aUpdate)
|
|||
// This needs to be done on the main thread, so we pass it along in
|
||||
// BackgroundThreadInfo
|
||||
nsresult rv = GetOSApplyToDir(osApplyToDir);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't get the OS apply to dir");
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Can't get the OS apply to dir"));
|
||||
return rv;
|
||||
}
|
||||
|
||||
SetOSApplyToDir(aUpdate, osApplyToDir);
|
||||
|
||||
mInfo.mIsOSUpdate = true;
|
||||
rv = NS_NewNativeLocalFile(osApplyToDir, false,
|
||||
getter_AddRefs(mInfo.mOSApplyToDir));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Can't create nsIFile for OS apply to dir");
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Can't create nsIFile for OS apply to dir"));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -49,30 +49,44 @@ namespace android {
|
|||
* This implements the (main) framebuffer management. This class
|
||||
* was adapted from the version in SurfaceFlinger
|
||||
*/
|
||||
|
||||
FramebufferSurface::FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, sp<IGraphicBufferAlloc>& alloc) :
|
||||
ConsumerBase(new BufferQueue(true, alloc)),
|
||||
FramebufferSurface::FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format,
|
||||
sp<BufferQueue>& bq) :
|
||||
#if ANDROID_VERSION >= 19
|
||||
ConsumerBase(bq, true),
|
||||
#else
|
||||
ConsumerBase(bq),
|
||||
#endif
|
||||
mDisplayType(disp),
|
||||
mCurrentBufferSlot(-1),
|
||||
mCurrentBuffer(0),
|
||||
lastHandle(0)
|
||||
{
|
||||
mName = "FramebufferSurface";
|
||||
mBufferQueue->setConsumerName(mName);
|
||||
mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
|
||||
GRALLOC_USAGE_HW_RENDER |
|
||||
GRALLOC_USAGE_HW_COMPOSER);
|
||||
mBufferQueue->setDefaultBufferFormat(format);
|
||||
mBufferQueue->setDefaultBufferSize(width, height);
|
||||
mBufferQueue->setSynchronousMode(true);
|
||||
mBufferQueue->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
|
||||
|
||||
#if ANDROID_VERSION >= 19
|
||||
sp<IGraphicBufferConsumer> consumer = mConsumer;
|
||||
#else
|
||||
sp<BufferQueue> consumer = mBufferQueue;
|
||||
consumer->setSynchronousMode(true);
|
||||
#endif
|
||||
consumer->setConsumerName(mName);
|
||||
consumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
|
||||
GRALLOC_USAGE_HW_RENDER |
|
||||
GRALLOC_USAGE_HW_COMPOSER);
|
||||
consumer->setDefaultBufferFormat(format);
|
||||
consumer->setDefaultBufferSize(width, height);
|
||||
consumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
|
||||
}
|
||||
|
||||
status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
BufferQueue::BufferItem item;
|
||||
#if ANDROID_VERSION >= 19
|
||||
status_t err = acquireBufferLocked(&item, 0);
|
||||
#else
|
||||
status_t err = acquireBufferLocked(&item);
|
||||
#endif
|
||||
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
|
||||
outBuffer = mCurrentBuffer;
|
||||
return NO_ERROR;
|
||||
|
@ -92,8 +106,13 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>&
|
|||
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
|
||||
item.mBuf != mCurrentBufferSlot) {
|
||||
// Release the previous buffer.
|
||||
#if ANDROID_VERSION >= 19
|
||||
err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
|
||||
EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
|
||||
#else
|
||||
err = releaseBufferLocked(mCurrentBufferSlot, EGL_NO_DISPLAY,
|
||||
EGL_NO_SYNC_KHR);
|
||||
#endif
|
||||
if (err != NO_ERROR && err != BufferQueue::STALE_BUFFER_SLOT) {
|
||||
ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
|
||||
return err;
|
||||
|
@ -136,7 +155,11 @@ status_t FramebufferSurface::setReleaseFenceFd(int fenceFd) {
|
|||
if (fenceFd >= 0) {
|
||||
sp<Fence> fence(new Fence(fenceFd));
|
||||
if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
|
||||
#if ANDROID_VERSION >= 19
|
||||
status_t err = addReleaseFence(mCurrentBufferSlot, mCurrentBuffer, fence);
|
||||
#else
|
||||
status_t err = addReleaseFence(mCurrentBufferSlot, fence);
|
||||
#endif
|
||||
ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
|
||||
strerror(-err), err);
|
||||
}
|
||||
|
@ -158,6 +181,10 @@ void FramebufferSurface::dump(String8& result) {
|
|||
ConsumerBase::dump(result);
|
||||
}
|
||||
|
||||
void FramebufferSurface::dump(String8& result, const char* prefix) {
|
||||
ConsumerBase::dump(result);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
}; // namespace android
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -34,13 +34,14 @@ class HWComposer;
|
|||
|
||||
class FramebufferSurface : public ConsumerBase {
|
||||
public:
|
||||
FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, sp<IGraphicBufferAlloc>& alloc);
|
||||
FramebufferSurface(int disp, uint32_t width, uint32_t height, uint32_t format, sp<BufferQueue>& bq);
|
||||
|
||||
bool isUpdateOnDemand() const { return false; }
|
||||
status_t setUpdateRectangle(const Rect& updateRect);
|
||||
status_t compositionComplete();
|
||||
|
||||
virtual void dump(String8& result);
|
||||
virtual void dump(String8& result, const char* prefix);
|
||||
|
||||
// setReleaseFenceFd stores a fence file descriptor that will signal when the
|
||||
// current buffer is no longer being read. This fence will be returned to
|
||||
|
|
|
@ -114,12 +114,17 @@ GonkDisplayJB::GonkDisplayJB()
|
|||
mBootAnimBuffer = mAlloc->createGraphicBuffer(mWidth, mHeight, surfaceformat, usage, &error);
|
||||
}
|
||||
|
||||
mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, mAlloc);
|
||||
#if ANDROID_VERSION >= 19
|
||||
sp<BufferQueue> bq = new BufferQueue(mAlloc);
|
||||
#else
|
||||
sp<BufferQueue> bq = new BufferQueue(true, mAlloc);
|
||||
#endif
|
||||
mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, bq);
|
||||
|
||||
#if ANDROID_VERSION == 17
|
||||
sp<SurfaceTextureClient> stc = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(mFBSurface->getBufferQueue()));
|
||||
#else
|
||||
sp<Surface> stc = new Surface(static_cast<sp<IGraphicBufferProducer> >(mFBSurface->getBufferQueue()));
|
||||
sp<Surface> stc = new Surface(static_cast<sp<IGraphicBufferProducer> >(bq));
|
||||
#endif
|
||||
mSTClient = stc;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче