This commit is contained in:
Ryan VanderMeulen 2014-01-13 17:52:40 -05:00
Родитель 84d939ac0b e7b8f32115
Коммит b998c68cd4
76 изменённых файлов: 1216 добавлений и 288 удалений

Просмотреть файл

@ -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();
}

Двоичный файл не отображается.

Просмотреть файл

@ -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

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Двоичный файл не отображается.

Просмотреть файл

@ -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;