Merge inbound to m-c

This commit is contained in:
Daniel Holbert 2012-12-27 13:53:16 -08:00
commit 2893d626ec
69 changed files with 1737 additions and 527 deletions

View File

@ -358,7 +358,7 @@ DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
// Ignore documents without presshell and not having root frame.
nsIPresShell* presShell = aDocument->GetShell();
if (!presShell || !presShell->GetRootFrame() || presShell->IsDestroying())
if (!presShell || presShell->IsDestroying())
return nullptr;
bool isRootDoc = nsCoreUtils::IsRootDocument(aDocument);

View File

@ -9,7 +9,7 @@
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
#include "nsCoreUtils.h"
#include "DocAccessible.h"
#include "DocAccessible-inl.h"
#include "nsEventShell.h"
#include "FocusManager.h"
#include "Role.h"
@ -213,6 +213,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
"Pending content insertions while initial accessible tree isn't created!");
}
// Initialize scroll support if needed.
if (!(mDocument->mDocFlags & DocAccessible::eScrollInitialized))
mDocument->AddScrollListener();
// Process content inserted notifications to update the tree. Process other
// notifications like DOM events and then flush event queue. If any new
// notifications are queued during this processing then they will be processed

View File

@ -65,6 +65,33 @@ DocAccessible::UpdateText(nsIContent* aTextNode)
mNotificationController->ScheduleTextUpdate(aTextNode);
}
inline void
DocAccessible::AddScrollListener()
{
// Delay scroll initializing until the document has a root frame.
if (!mPresShell->GetRootFrame())
return;
mDocFlags |= eScrollInitialized;
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollable();
if (sf) {
sf->AddScrollPositionListener(this);
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eDocCreate))
logging::Text("add scroll listener");
#endif
}
}
inline void
DocAccessible::RemoveScrollListener()
{
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollable();
if (sf)
sf->RemoveScrollPositionListener(this);
}
inline void
DocAccessible::NotifyOfLoad(uint32_t aLoadEventType)
{

View File

@ -75,7 +75,7 @@ DocAccessible::
nsIPresShell* aPresShell) :
HyperTextAccessibleWrap(aRootContent, this),
mDocumentNode(aDocument), mScrollPositionChangedTicks(0),
mLoadState(eTreeConstructionPending), mLoadEventType(0),
mLoadState(eTreeConstructionPending), mDocFlags(0), mLoadEventType(0),
mVirtualCursor(nullptr),
mPresShell(aPresShell)
{
@ -93,18 +93,6 @@ DocAccessible::
// If this is a XUL Document, it should not implement nsHyperText
if (mDocumentNode && mDocumentNode->IsXUL())
mGenericTypes &= ~eHyperText;
// For GTK+ native window, we do nothing here.
if (!mDocumentNode)
return;
// DocManager creates document accessible when scrollable frame is
// available already, it should be safe time to add scroll listener.
AddScrollListener();
// We provide a virtual cursor if this is a root doc or if it's a tab doc.
mIsCursorable = (!(mDocumentNode->GetParentDocument()) ||
nsCoreUtils::IsTabDocument(mDocumentNode));
}
DocAccessible::~DocAccessible()
@ -145,7 +133,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DocAccessible)
NS_INTERFACE_MAP_ENTRY(nsIAccessiblePivotObserver)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleDocument)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleCursorable,
mIsCursorable)
(mDocFlags & eCursorable))
foundInterface = 0;
nsresult status;
@ -502,7 +490,8 @@ DocAccessible::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor)
if (IsDefunct())
return NS_ERROR_FAILURE;
NS_ENSURE_TRUE(mIsCursorable, NS_ERROR_NOT_IMPLEMENTED);
if (!(mDocFlags & eCursorable))
return NS_OK;
if (!mVirtualCursor) {
mVirtualCursor = new nsAccessiblePivot(this);
@ -798,36 +787,6 @@ DocAccessible::ScrollTimerCallback(nsITimer* aTimer, void* aClosure)
}
}
// DocAccessible protected member
void
DocAccessible::AddScrollListener()
{
if (!mPresShell)
return;
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollableExternal();
if (sf) {
sf->AddScrollPositionListener(this);
#ifdef A11Y_LOG
if (logging::IsEnabled(logging::eDocCreate))
logging::Text("add scroll listener");
#endif
}
}
// DocAccessible protected member
void
DocAccessible::RemoveScrollListener()
{
if (!mPresShell)
return;
nsIScrollableFrame* sf = mPresShell->GetRootScrollFrameAsScrollableExternal();
if (sf) {
sf->RemoveScrollPositionListener(this);
}
}
////////////////////////////////////////////////////////////////////////////////
// nsIScrollPositionListener
@ -1511,6 +1470,11 @@ DocAccessible::NotifyOfLoading(bool aIsReloading)
void
DocAccessible::DoInitialUpdate()
{
// We provide a virtual cursor if this is a root doc or if it's a tab doc.
if (!(mDocumentNode->GetParentDocument()) ||
nsCoreUtils::IsTabDocument(mDocumentNode))
mDocFlags |= eCursorable;
mLoadState |= eTreeConstructed;
// The content element may be changed before the initial update and then we

View File

@ -333,8 +333,11 @@ protected:
*/
void ProcessLoad();
void AddScrollListener();
void RemoveScrollListener();
/**
* Add/remove scroll listeners, @see nsIScrollPositionListener interface.
*/
void AddScrollListener();
void RemoveScrollListener();
/**
* Append the given document accessible to this document's child document
@ -482,6 +485,17 @@ protected:
protected:
/**
* State and property flags, kept by mDocFlags.
*/
enum {
// Whether scroll listeners were added.
eScrollInitialized = 1 << 0,
// Whether we support nsIAccessibleCursorable.
eCursorable = 1 << 1
};
/**
* Cache of accessibles within this document accessible.
*/
@ -496,7 +510,12 @@ protected:
/**
* Bit mask of document load states (@see LoadState).
*/
uint32_t mLoadState;
uint32_t mLoadState : 3;
/**
* Bit mask of other states and props.
*/
uint32_t mDocFlags : 28;
/**
* Type of document load event fired after the document is loaded completely.
@ -516,11 +535,6 @@ protected:
nsTArray<nsRefPtr<DocAccessible> > mChildDocuments;
/**
* Whether we support nsIAccessibleCursorable, used when querying the interface.
*/
bool mIsCursorable;
/**
* The virtual cursor of the document when it supports nsIAccessibleCursorable.
*/

View File

@ -191,7 +191,7 @@ this.EventManager = {
if (txtIface.characterCount)
throw x;
}
this.present(Presentation, textChanged(
this.present(Presentation.textChanged(
isInserted, event.start, event.length,
text, event.modifiedText));
}

View File

@ -32,7 +32,6 @@
"test1: frameDocCheckbox");
testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
"test1: frameDocTextbox");
frameDoc.designMode = "on";
testStates(frameDoc, 0, EXT_STATE_EDITABLE, STATE_READONLY, 0,
"test2: frameDoc");

View File

@ -461,9 +461,6 @@ pref("shutdown.watchdog.timeoutSecs", 5);
pref("b2g.update.apply-prompt-timeout", 60000); // milliseconds
// Amount of time to wait after the user is idle before prompting to apply an update
pref("b2g.update.apply-idle-timeout", 600000); // milliseconds
// Amount of time the updater waits for the process to exit cleanly before
// forcefully exiting the process
pref("b2g.update.self-destruct-timeout", 5000); // milliseconds
pref("app.update.enabled", true);
pref("app.update.auto", false);

View File

@ -18,14 +18,9 @@ let log =
function log_dump(msg) { dump("UpdatePrompt: "+ msg +"\n"); } :
function log_noop(msg) { };
const APPLY_PROMPT_TIMEOUT =
Services.prefs.getIntPref("b2g.update.apply-prompt-timeout");
const APPLY_IDLE_TIMEOUT =
Services.prefs.getIntPref("b2g.update.apply-idle-timeout");
const SELF_DESTRUCT_TIMEOUT =
Services.prefs.getIntPref("b2g.update.self-destruct-timeout");
const PREF_APPLY_PROMPT_TIMEOUT = "b2g.update.apply-prompt-timeout";
const PREF_APPLY_IDLE_TIMEOUT = "b2g.update.apply-idle-timeout";
const APPLY_IDLE_TIMEOUT_SECONDS = APPLY_IDLE_TIMEOUT / 1000;
const NETWORK_ERROR_OFFLINE = 111;
XPCOMUtils.defineLazyServiceGetter(Services, "aus",
@ -108,6 +103,14 @@ UpdatePrompt.prototype = {
_waitingForIdle: false,
_updateCheckListner: null,
get applyPromptTimeout() {
return Services.prefs.getIntPref(PREF_APPLY_PROMPT_TIMEOUT);
},
get applyIdleTimeout() {
return Services.prefs.getIntPref(PREF_APPLY_IDLE_TIMEOUT);
},
// nsIUpdatePrompt
// FIXME/bug 737601: we should have users opt-in to downloading
@ -130,14 +133,15 @@ UpdatePrompt.prototype = {
// update quietly without user intervention.
this.sendUpdateEvent("update-downloaded", aUpdate);
if (Services.idle.idleTime >= APPLY_IDLE_TIMEOUT) {
if (Services.idle.idleTime >= this.applyIdleTimeout) {
this.showApplyPrompt(aUpdate);
return;
}
let applyIdleTimeoutSeconds = this.applyIdleTimeout / 1000;
// We haven't been idle long enough, so register an observer
log("Update is ready to apply, registering idle timeout of " +
APPLY_IDLE_TIMEOUT_SECONDS + " seconds before prompting.");
applyIdleTimeoutSeconds + " seconds before prompting.");
this._update = aUpdate;
this.waitForIdle();
@ -165,7 +169,7 @@ UpdatePrompt.prototype = {
}
this._waitingForIdle = true;
Services.idle.addIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
Services.idle.addIdleObserver(this, this.applyIdleTimeout / 1000);
Services.obs.addObserver(this, "quit-application", false);
},
@ -185,7 +189,7 @@ UpdatePrompt.prototype = {
// Schedule a fallback timeout in case the UI is unable to respond or show
// a prompt for some reason.
this._applyPromptTimer = this.createTimer(APPLY_PROMPT_TIMEOUT);
this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
},
sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
@ -429,7 +433,7 @@ UpdatePrompt.prototype = {
this.showApplyPrompt(this._update);
// Fall through
case "quit-application":
Services.idle.removeIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
Services.idle.removeIdleObserver(this, this.applyIdleTimeout / 1000);
Services.obs.removeObserver(this, "quit-application");
break;
case "update-check-start":

View File

@ -3728,6 +3728,9 @@ let SessionStoreInternal = {
for (let i = oState.windows.length - 1; i >= 0; i--) {
if (oState.windows[i].isPrivate) {
oState.windows.splice(i, 1);
if (oState.selectedWindow >= i) {
oState.selectedWindow--;
}
}
}
for (let i = oState._closedWindows.length - 1; i >= 0; i--) {

View File

@ -141,6 +141,7 @@ ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
MOCHITEST_BROWSER_FILES += \
browser_354894_perwindowpb.js \
browser_394759_perwindowpb.js \
browser_819510_perwindowpb.js \
$(NULL)
else
MOCHITEST_BROWSER_FILES += \

View File

@ -0,0 +1,181 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const originalState = ss.getBrowserState();
/** Private Browsing Test for Bug 819510 **/
function test() {
waitForExplicitFinish();
registerCleanupFunction(function() {
Services.prefs.clearUserPref("browser.sessionstore.interval");
ss.setBrowserState(originalState);
});
runNextTest();
}
let tests = [test_1, test_2, test_3 ];
const testState = {
windows: [{
tabs: [
{ entries: [{ url: "about:blank" }] },
]
}]
};
function runNextTest() {
// Set an empty state
closeAllButPrimaryWindow();
// Run the next test, or finish
if (tests.length) {
let currentTest = tests.shift();
waitForBrowserState(testState, currentTest);
} else {
Services.prefs.clearUserPref("browser.sessionstore.interval");
ss.setBrowserState(originalState);
finish();
}
}
// Test opening default mochitest-normal-private-normal-private windows
// (saving the state with last window being private)
function test_1() {
testOnWindow(false, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/1");
testOnWindow(true, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/2");
testOnWindow(false, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/3");
testOnWindow(true, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/4");
let curState = JSON.parse(ss.getBrowserState());
is (curState.windows.length, 5, "Browser has opened 5 windows");
is (curState.windows[2].isPrivate, true, "Window is private");
is (curState.windows[4].isPrivate, true, "Last window is private");
is (curState.selectedWindow, 5, "Last window opened is the one selected");
forceWriteState(function(state) {
is(state.windows.length, 3,
"sessionstore state: 3 windows in data being written to disk");
is (state.selectedWindow, 3,
"Selected window is updated to match one of the saved windows");
state.windows.forEach(function(win) {
is(!win.isPrivate, true, "Saved window is not private");
});
is(state._closedWindows.length, 0,
"sessionstore state: no closed windows in data being written to disk");
runNextTest();
});
});
});
});
});
}
// Test opening default mochitest window + 2 private windows
function test_2() {
testOnWindow(true, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/1");
testOnWindow(true, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/2");
let curState = JSON.parse(ss.getBrowserState());
is (curState.windows.length, 3, "Browser has opened 3 windows");
is (curState.windows[1].isPrivate, true, "Window 1 is private");
is (curState.windows[2].isPrivate, true, "Window 2 is private");
is (curState.selectedWindow, 3, "Last window opened is the one selected");
forceWriteState(function(state) {
is(state.windows.length, 1,
"sessionstore state: 1 windows in data being writted to disk");
is (state.selectedWindow, 1,
"Selected window is updated to match one of the saved windows");
is(state._closedWindows.length, 0,
"sessionstore state: no closed windows in data being writted to disk");
runNextTest();
});
});
});
}
// Test opening default-normal-private-normal windows and closing a normal window
function test_3() {
testOnWindow(false, function(normalWindow) {
let tab = normalWindow.gBrowser.addTab("http://www.example.com/1");
whenBrowserLoaded(tab.linkedBrowser, function() {
testOnWindow(true, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/2");
testOnWindow(false, function(aWindow) {
aWindow.gBrowser.addTab("http://www.example.com/3");
let curState = JSON.parse(ss.getBrowserState());
is (curState.windows.length, 4, "Browser has opened 4 windows");
is (curState.windows[2].isPrivate, true, "Window 2 is private");
is (curState.selectedWindow, 4, "Last window opened is the one selected");
waitForWindowClose(normalWindow, function() {
forceWriteState(function(state) {
is(state.windows.length, 2,
"sessionstore state: 2 windows in data being writted to disk");
is(state.selectedWindow, 2,
"Selected window is updated to match one of the saved windows");
state.windows.forEach(function(win) {
is(!win.isPrivate, true, "Saved window is not private");
});
is(state._closedWindows.length, 1,
"sessionstore state: 1 closed window in data being writted to disk");
state._closedWindows.forEach(function(win) {
is(!win.isPrivate, true, "Closed window is not private");
});
runNextTest();
});
});
});
});
});
});
}
function waitForWindowClose(aWin, aCallback) {
Services.obs.addObserver(function observe(aSubject, aTopic, aData) {
if (aTopic == "domwindowclosed" && aWin == aSubject) {
Services.obs.removeObserver(observe, aTopic);
checkWindowIsClosed(aWin, aCallback);
}
}, "domwindowclosed", false);
aWin.close();
}
function checkWindowIsClosed(aWin, aCallback) {
if (aWin.closed) {
info("Window is closed");
executeSoon(aCallback);
} else {
executeSoon(function() {
checkWindowIsClosed(aWin, aCallback);
});
}
}
function forceWriteState(aCallback) {
Services.obs.addObserver(function observe(aSubject, aTopic, aData) {
if (aTopic == "sessionstore-state-write") {
Services.obs.removeObserver(observe, aTopic);
aSubject.QueryInterface(Ci.nsISupportsString);
aCallback(JSON.parse(aSubject.data));
}
}, "sessionstore-state-write", false);
Services.prefs.setIntPref("browser.sessionstore.interval", 0);
}
function testOnWindow(aIsPrivate, aCallback) {
let win = OpenBrowserWindow({private: aIsPrivate});
win.addEventListener("load", function onLoad() {
win.removeEventListener("load", onLoad, false);
executeSoon(function() { aCallback(win); });
}, false);
}

View File

@ -1,16 +0,0 @@
. $topsrcdir/build/macosx/mozconfig.leopard
ac_add_options --enable-debug
ac_add_options --enable-trace-malloc
ac_add_options --enable-signmar
ENABLE_MARIONETTE=1
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
ac_add_options --with-macbundlename-prefix=Firefox
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1
. "$topsrcdir/build/mozconfig.common.override"

View File

@ -1,17 +0,0 @@
[
{
"clang_version": "r170890"
},
{
"size": 47,
"digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
"algorithm": "sha512",
"filename": "setup.sh"
},
{
"size": 56126352,
"digest": "e156e2a39abd5bf272ee30748a6825f22ddd27565b097c66662a2a6f2e9892bc5b4bf30a3552dffbe867dbfc39e7ee086e0b2cd7935f6ea216c0cf936178a88f",
"algorithm": "sha512",
"filename": "clang.tar.bz2"
}
]

View File

@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#downloadsRichListBox {
/** The default listbox appearance comes with an unwanted margin. **/
-moz-appearance: none;
margin: 0;
}

View File

@ -1,16 +1,16 @@
richlistitem.download {
height: 7em;
/* 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/. */
#downloadsRichListBox {
/** The default listbox appearance comes with an unwanted margin. **/
-moz-appearance: none;
margin: 0;
padding: 8px;
-moz-padding-end: 0;
}
richlistitem.download:first-child {
border-top: 1px solid transparent;
}
richlistitem.download:last-child {
border-bottom: 1px solid transparent;
#downloadsRichListBox > richlistitem.download {
height: 6em;
padding: 5px 8px;
}
.downloadTypeIcon {
@ -25,7 +25,7 @@ richlistitem.download:last-child {
}
.downloadTarget {
margin-bottom: 6px;
margin-bottom: 3px;
cursor: inherit;
}
@ -37,6 +37,7 @@ richlistitem.download:last-child {
.downloadButton {
-moz-appearance: none;
background: transparent;
min-width: 0;
min-height: 0;
margin: 3px;
@ -45,10 +46,6 @@ richlistitem.download:last-child {
list-style-image: url("chrome://browser/skin/downloads/buttons.png");
}
.downloadButton > .button-box {
padding: 0;
}
/*** Button icons ***/
.downloadButton.downloadCancel {

View File

@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#downloadsRichListBox {
/** The default listbox appearance comes with an unwanted margin. **/
-moz-appearance: none;
margin: 0;
}

View File

@ -1,32 +0,0 @@
. $topsrcdir/build/macosx/mozconfig.common
# Mac builds don't normally have to be handled as cross
# compilation, but some of the libraries on the bots
# (IDL for example) are built only for one arch.
HOST_CC=$CC
HOST_CXX=$CXX
# These must be set for cross builds, and don't hurt straight builds.
RANLIB=ranlib
AR=ar
AS=$CC
LD=ld
STRIP="strip"
MOZ_CAN_RUN_PROGRAMS=1
# We do 32 bit builds for leopard
TARGET_CPU=i386
CC="$CC -arch $TARGET_CPU"
CXX="$CXX -arch $TARGET_CPU"
NATIVE_CPU=`$topsrcdir/build/autoconf/config.guess | cut -f1 -d-`
if test "$NATIVE_CPU" != "$TARGET_CPU" ; then
CROSS_COMPILE=1
fi
# Note, the version (10) is used by libffi's configure.
ac_add_options --target=i386-apple-darwin10
ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.6.sdk

View File

@ -270,6 +270,7 @@ MOCHITEST_FILES_A = \
test_domparser_null_char.html \
test_bug811701.html \
test_bug811701.xhtml \
test_bug820909.html \
$(NULL)
MOCHITEST_FILES_B = \

View File

@ -0,0 +1,87 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=820909
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 820909</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=820909">Mozilla Bug 820909</a>
<p id="display"></p>
<div id="content" style="display: none">
<span dİsabled="CAPS"></span>
</div>
<pre id="test">
<script>
var bogusScriptRan = false;
</script>
<script type="applİcation/javascript">
bogusScriptRan = true;
</script>
<script type="application/javascript">
/** Test for Bug 820909 **/
// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=820909#c7 item 1
ok(!bogusScriptRan, "Script types should be ASCII case-insensitive");
// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=820909#c7 item 2
var input = document.createElement("input");
input.type = "radİo";
is(input.type, "text", "Input types should be ASCII case-insensitive");
// XXX Not sure how to test items 3, 4, 5
// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=820909#c7 item 6
is(document.querySelector("[dİsabled='caps']"), null,
"Checking whether an attribute is case-sensitive for selector-matching " +
"purposes should be ASCII case-insensitive on the attr name");
// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=820909#c7 item 7
$("content").style.width = "0";
$("content").style.width = "1İn";
is($("content").style.width, "0px",
"CSS unit names should be ASCII case-insensitive");
// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=820909#c7 item 8
$("content").style.setProperty("animation-name", "a");
$("content").style.setProperty("-moz-anİmation-name", "b");
is($("content").style.animationName, "a",
"CSS property aliases should be ASCII case-insensitive");
// XXXbz don't know how to test item 9
// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=820909#c7 item 10
$("content").innerHTML = "<table><input type='hİdden'></table>";
is($("content").querySelector("input").parentNode, $("content"),
"Inputs that aren't actually type='hidden' should not be allowed as " +
"table kids");
// XXXbz add test for item 11?
// XXXbz add test for item 12?
// Test for https://bugzilla.mozilla.org/show_bug.cgi?id=820909#c7 item 13
$("content").style.setProperty("animation-name", "a");
$("content").style.setProperty("anİmation-name", "b");
is($("content").style.animationName, "a",
"CSS property names should be ASCII case-insensitive");
$("content").style.setProperty("display", "none");
$("content").style.setProperty("display", "İnline");
is($("content").style.display, "none",
"CSS keywords should be ASCII case-insensitive");
$("content").style.setProperty("color", "white");
$("content").style.setProperty("color", "İndigo");
is($("content").style.color, "white",
"CSS color names should be ASCII case-insensitive");
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,89 @@
/* -*- Mode: C++; 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/. */
#include "mozilla/dom/HTMLHeadingElement.h"
#include "mozilla/dom/HTMLHeadingElementBinding.h"
#include "mozilla/Util.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
#include "nsRuleData.h"
#include "mozAutoDocUpdate.h"
DOMCI_NODE_DATA(HTMLHeadingElement, mozilla::dom::HTMLHeadingElement)
NS_IMPL_NS_NEW_HTML_ELEMENT(Heading)
namespace mozilla {
namespace dom {
HTMLHeadingElement::~HTMLHeadingElement()
{
}
NS_IMPL_ADDREF_INHERITED(HTMLHeadingElement, Element)
NS_IMPL_RELEASE_INHERITED(HTMLHeadingElement, Element)
// QueryInterface implementation for HTMLHeadingElement
NS_INTERFACE_TABLE_HEAD(HTMLHeadingElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(HTMLHeadingElement,
nsIDOMHTMLHeadingElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(HTMLHeadingElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLHeadingElement)
NS_IMPL_ELEMENT_CLONE(HTMLHeadingElement)
JSObject*
HTMLHeadingElement::WrapNode(JSContext *aCx, JSObject *aScope, bool *aTriedToWrap)
{
return HTMLHeadingElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
}
NS_IMPL_STRING_ATTR(HTMLHeadingElement, Align, align)
bool
HTMLHeadingElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
return ParseDivAlignValue(aValue, aResult);
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}
static void
MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
{
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
}
NS_IMETHODIMP_(bool)
HTMLHeadingElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry* const map[] = {
sDivAlignAttributeMap,
sCommonAttributeMap
};
return FindAttributeDependence(aAttribute, map);
}
nsMapRuleToAttributesFunc
HTMLHeadingElement::GetAttributeMappingFunction() const
{
return &MapAttributesIntoRule;
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,62 @@
/* -*- Mode: C++; 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/. */
#ifndef mozilla_dom_HTMLHeadingElement_h
#define mozilla_dom_HTMLHeadingElement_h
#include "nsIDOMHTMLHeadingElement.h"
#include "nsGenericHTMLElement.h"
namespace mozilla {
namespace dom {
class HTMLHeadingElement MOZ_FINAL : public nsGenericHTMLElement,
public nsIDOMHTMLHeadingElement
{
public:
HTMLHeadingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
SetIsDOMBinding();
}
virtual ~HTMLHeadingElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLHeadingElement
NS_DECL_NSIDOMHTMLHEADINGELEMENT
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
// The XPCOM versions of GetAlign and SetAlign are fine for us for
// use from WebIDL.
protected:
virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
bool *aTriedToWrap) MOZ_OVERRIDE;
};
} // namespace mozilla
} // namespace dom
#endif // mozilla_dom_HTMLHeadingElement_h

View File

@ -33,6 +33,7 @@ EXPORTS_mozilla/dom = \
HTMLDivElement.h \
HTMLFontElement.h \
HTMLFrameSetElement.h \
HTMLHeadingElement.h \
HTMLLabelElement.h \
HTMLUnknownElement.h
@ -59,7 +60,7 @@ CPPSRCS = \
nsHTMLFrameElement.cpp \
HTMLFrameSetElement.cpp \
nsHTMLHRElement.cpp \
nsHTMLHeadingElement.cpp \
HTMLHeadingElement.cpp \
nsHTMLIFrameElement.cpp \
nsHTMLImageElement.cpp \
nsHTMLInputElement.cpp \

View File

@ -1,125 +0,0 @@
/* -*- Mode: C++; 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/. */
#include "mozilla/Util.h"
#include "nsIDOMHTMLHeadingElement.h"
#include "nsIDOMEventTarget.h"
#include "nsGenericHTMLElement.h"
#include "nsGkAtoms.h"
#include "nsStyleConsts.h"
#include "nsMappedAttributes.h"
#include "nsRuleData.h"
#include "mozAutoDocUpdate.h"
using namespace mozilla;
using namespace mozilla::dom;
class nsHTMLHeadingElement : public nsGenericHTMLElement,
public nsIDOMHTMLHeadingElement
{
public:
nsHTMLHeadingElement(already_AddRefed<nsINodeInfo> aNodeInfo);
virtual ~nsHTMLHeadingElement();
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMNode
NS_FORWARD_NSIDOMNODE_TO_NSINODE
// nsIDOMElement
NS_FORWARD_NSIDOMELEMENT_TO_GENERIC
// nsIDOMHTMLElement
NS_FORWARD_NSIDOMHTMLELEMENT_TO_GENERIC
// nsIDOMHTMLHeadingElement
NS_DECL_NSIDOMHTMLHEADINGELEMENT
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult);
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo();
virtual nsIDOMNode* AsDOMNode() { return this; }
};
NS_IMPL_NS_NEW_HTML_ELEMENT(Heading)
nsHTMLHeadingElement::nsHTMLHeadingElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
{
}
nsHTMLHeadingElement::~nsHTMLHeadingElement()
{
}
NS_IMPL_ADDREF_INHERITED(nsHTMLHeadingElement, Element)
NS_IMPL_RELEASE_INHERITED(nsHTMLHeadingElement, Element)
DOMCI_NODE_DATA(HTMLHeadingElement, nsHTMLHeadingElement)
// QueryInterface implementation for nsHTMLHeadingElement
NS_INTERFACE_TABLE_HEAD(nsHTMLHeadingElement)
NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLHeadingElement,
nsIDOMHTMLHeadingElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLHeadingElement,
nsGenericHTMLElement)
NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLHeadingElement)
NS_IMPL_ELEMENT_CLONE(nsHTMLHeadingElement)
NS_IMPL_STRING_ATTR(nsHTMLHeadingElement, Align, align)
bool
nsHTMLHeadingElement::ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult)
{
if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
return ParseDivAlignValue(aValue, aResult);
}
return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
aResult);
}
static void
MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
{
nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
}
NS_IMETHODIMP_(bool)
nsHTMLHeadingElement::IsAttributeMapped(const nsIAtom* aAttribute) const
{
static const MappedAttributeEntry* const map[] = {
sDivAlignAttributeMap,
sCommonAttributeMap
};
return FindAttributeDependence(aAttribute, map);
}
nsMapRuleToAttributesFunc
nsHTMLHeadingElement::GetAttributeMappingFunction() const
{
return &MapAttributesIntoRule;
}

View File

@ -496,6 +496,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
#include "DOMError.h"
#include "DOMRequest.h"
#include "nsIOpenWindowEventDetail.h"
#include "nsIAsyncScrollEventDetail.h"
#include "nsIDOMGlobalObjectConstructor.h"
#include "nsIDOMCanvasRenderingContext2D.h"
#include "DOMFileHandle.h"
@ -1544,6 +1545,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
EVENTTARGET_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(OpenWindowEventDetail, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(AsyncScrollEventDetail, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA_WITH_NAME(DOMFileHandle, FileHandle, nsEventTargetSH,
EVENTTARGET_SCRIPTABLE_FLAGS)
@ -4016,6 +4019,10 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIOpenWindowEventDetail)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(AsyncScrollEventDetail, nsIAsyncScrollEventDetail)
DOM_CLASSINFO_MAP_ENTRY(nsIAsyncScrollEventDetail)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(DOMFileHandle, nsIDOMFileHandle)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileHandle)
DOM_CLASSINFO_MAP_END

View File

@ -453,6 +453,7 @@ DOMCI_CLASS(CameraCapabilities)
DOMCI_CLASS(DOMError)
DOMCI_CLASS(DOMRequest)
DOMCI_CLASS(OpenWindowEventDetail)
DOMCI_CLASS(AsyncScrollEventDetail)
DOMCI_CLASS(DOMFileHandle)
DOMCI_CLASS(FileRequest)

View File

@ -302,6 +302,9 @@ DOMInterfaces = {
'HTMLDocument': {
'nativeType': 'nsHTMLDocument',
'register': False,
'hasXPConnectImpls': True,
'hasInstanceInterface': 'nsIDOMHTMLDocument',
'resultNotAddRefed': [ 'body', 'head', 'images', 'embeds', 'plugins',
'links', 'forms', 'scripts', 'anchors', 'applets' ],
'implicitJSContext': [ 'open', 'write', 'writeln' ]

View File

@ -27,9 +27,9 @@ SetJsObject(JSContext* aContext,
jsval v;
if (aData[i].value().type() == BluetoothValue::TnsString) {
nsString data = aData[i].value().get_nsString();
JSString* JsData = JS_NewStringCopyN(aContext,
NS_ConvertUTF16toUTF8(data).get(),
data.Length());
JSString* JsData = JS_NewUCStringCopyN(aContext,
data.BeginReading(),
data.Length());
NS_ENSURE_TRUE(JsData, false);
v = STRING_TO_JSVAL(JsData);
} else if (aData[i].value().type() == BluetoothValue::Tuint32_t) {

View File

@ -19,6 +19,7 @@
#include "nsIDOMCustomEvent.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsVariant.h"
#include "nsAsyncScrollEventDetail.h"
using mozilla::dom::Element;
using mozilla::dom::TabParent;
@ -68,6 +69,40 @@ CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote)
return popupFrameElement.forget();
}
bool
DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName,
nsISupports *aDetailValue)
{
NS_ENSURE_TRUE(aFrameElement, false);
nsIPresShell *shell = aFrameElement->OwnerDoc()->GetShell();
nsRefPtr<nsPresContext> presContext;
if (shell) {
presContext = shell->GetPresContext();
}
nsCOMPtr<nsIDOMEvent> domEvent;
nsEventDispatcher::CreateEvent(presContext, nullptr,
NS_LITERAL_STRING("customevent"),
getter_AddRefs(domEvent));
NS_ENSURE_TRUE(domEvent, false);
nsCOMPtr<nsIWritableVariant> detailVariant = new nsVariant();
nsresult rv = detailVariant->SetAsISupports(aDetailValue);
NS_ENSURE_SUCCESS(rv, false);
nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
NS_ENSURE_TRUE(customEvent, false);
customEvent->InitCustomEvent(aEventName,
/* bubbles = */ true,
/* cancelable = */ false,
detailVariant);
customEvent->SetTrusted(true);
// Dispatch the event.
nsEventStatus status = nsEventStatus_eIgnore;
rv = nsEventDispatcher::DispatchDOMEvent(aFrameElement, nullptr,
domEvent, presContext, &status);
return NS_SUCCEEDED(rv);
}
/**
* Dispatch a mozbrowseropenwindow event to the given opener frame element.
* The "popup iframe" (event.detail.frameElement) will be |aPopupFrameElement|.
@ -90,40 +125,15 @@ DispatchOpenWindowEvent(Element* aOpenerFrameElement,
nsRefPtr<nsOpenWindowEventDetail> detail =
new nsOpenWindowEventDetail(aURL, aName, aFeatures,
aPopupFrameElement->AsDOMNode());
nsCOMPtr<nsIWritableVariant> detailVariant = new nsVariant();
nsresult rv = detailVariant->SetAsISupports(detail);
NS_ENSURE_SUCCESS(rv, false);
// Create the CustomEvent.
nsIPresShell *shell = aOpenerFrameElement->OwnerDoc()->GetShell();
nsRefPtr<nsPresContext> presContext;
if (shell) {
presContext = shell->GetPresContext();
}
nsCOMPtr<nsIDOMEvent> domEvent;
nsEventDispatcher::CreateEvent(presContext, nullptr,
NS_LITERAL_STRING("customevent"),
getter_AddRefs(domEvent));
NS_ENSURE_TRUE(domEvent, false);
nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
NS_ENSURE_TRUE(customEvent, false);
customEvent->InitCustomEvent(NS_LITERAL_STRING("mozbrowseropenwindow"),
/* bubbles = */ true,
/* cancelable = */ false,
detailVariant);
customEvent->SetTrusted(true);
// Dispatch the event.
nsEventStatus status = nsEventStatus_eIgnore;
rv = nsEventDispatcher::DispatchDOMEvent(aOpenerFrameElement, nullptr,
domEvent, presContext, &status);
NS_ENSURE_SUCCESS(rv, false);
bool dispatchSucceeded =
DispatchCustomDOMEvent(aOpenerFrameElement,
NS_LITERAL_STRING("mozbrowseropenwindow"),
detail);
// If the iframe is not in some document's DOM at this point, the embedder
// has "blocked" the popup.
return aPopupFrameElement->IsInDoc();
return (dispatchSucceeded && aPopupFrameElement->IsInDoc());
}
} // anonymous namespace
@ -131,8 +141,8 @@ DispatchOpenWindowEvent(Element* aOpenerFrameElement,
namespace mozilla {
/*static*/ bool
BrowserElementParent::OpenWindowOOP(mozilla::dom::TabParent* aOpenerTabParent,
mozilla::dom::TabParent* aPopupTabParent,
BrowserElementParent::OpenWindowOOP(TabParent* aOpenerTabParent,
TabParent* aPopupTabParent,
const nsAString& aURL,
const nsAString& aName,
const nsAString& aFeatures)
@ -230,4 +240,21 @@ BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
return !!*aReturnWindow;
}
bool
BrowserElementParent::DispatchAsyncScrollEvent(TabParent* aTabParent,
const gfx::Rect& aContentRect,
const gfx::Size& aContentSize)
{
nsIDOMElement* element = aTabParent->GetOwnerElement();
nsCOMPtr<Element> frameElement = do_QueryInterface(element);
// Create the event's detail object.
nsRefPtr<nsAsyncScrollEventDetail> detail =
new nsAsyncScrollEventDetail(aContentRect.x, aContentRect.y,
aContentRect.width, aContentRect.height,
aContentSize.width, aContentSize.height);
return DispatchCustomDOMEvent(frameElement,
NS_LITERAL_STRING("mozbrowserasyncscroll"),
detail);
}
} // namespace mozilla

View File

@ -16,6 +16,11 @@ namespace dom {
class TabParent;
}
namespace gfx{
struct Rect;
struct Size;
}
/**
* BrowserElementParent implements a portion of the parent-process side of
* <iframe mozbrowser>.
@ -63,8 +68,8 @@ public:
* window.open request.
*/
static bool
OpenWindowOOP(mozilla::dom::TabParent* aOpenerTabParent,
mozilla::dom::TabParent* aPopupTabParent,
OpenWindowOOP(dom::TabParent* aOpenerTabParent,
dom::TabParent* aPopupTabParent,
const nsAString& aURL,
const nsAString& aName,
const nsAString& aFeatures);
@ -86,6 +91,26 @@ public:
const nsAString& aName,
const nsACString& aFeatures,
nsIDOMWindow** aReturnWindow);
/**
* Fire a mozbrowserasyncscroll CustomEvent on the given TabParent's frame element.
* This event's detail is an instance of nsIAsyncScrollEventDetail.
*
* @param aContentRect: The portion of the page which is currently visible
* onscreen in CSS pixels.
*
* @param aContentSize: The content width/height in CSS pixels.
*
* aContentRect.top + aContentRect.height may be larger than aContentSize.height.
* This indicates that the content is over-scrolled, which occurs when the
* page "rubber-bands" after being scrolled all the way to the bottom.
* Similarly, aContentRect.left + aContentRect.width may be greater than
* contentSize.width, and both left and top may be negative.
*/
static bool
DispatchAsyncScrollEvent(dom::TabParent* aTabParent,
const gfx::Rect& aContentRect,
const gfx::Size& aContentSize);
};
} // namespace mozilla

View File

@ -1,3 +1,6 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 sts=2 et: */
/* 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/. */
@ -184,6 +187,7 @@ const ContentPanning = {
let target;
let isScrolling = false;
let oldX, oldY, newX, newY;
let win, doc, htmlNode, bodyNode;
function doScroll(node, delta) {
if (node instanceof Ci.nsIDOMHTMLElement) {
@ -192,12 +196,32 @@ const ContentPanning = {
node.scrollTop += delta.y;
newX = node.scrollLeft, newY = node.scrollTop;
return (newX != oldX || newY != oldY);
} else {
} else if (node instanceof Ci.nsIDOMWindow) {
win = node;
doc = win.document;
// "overflow:hidden" on either the <html> or the <body> node should
// prevent the user from scrolling the root viewport.
if (doc instanceof Ci.nsIDOMHTMLDocument) {
htmlNode = doc.documentElement;
bodyNode = doc.body;
if (win.getComputedStyle(htmlNode, null).overflowX == "hidden" ||
win.getComputedStyle(bodyNode, null).overflowX == "hidden") {
delta.x = 0;
}
if (win.getComputedStyle(htmlNode, null).overflowY == "hidden" ||
win.getComputedStyle(bodyNode, null).overflowY == "hidden") {
delta.y = 0;
}
}
oldX = node.scrollX, oldY = node.scrollY;
node.scrollBy(delta.x, delta.y);
newX = node.scrollX, newY = node.scrollY;
return (newX != oldX || newY != oldY);
}
// If we get here, |node| isn't an HTML element and it's not a window,
// but findPannable apparently thought it was scrollable... What is it?
return false;
};
function scroll(delta) {

View File

@ -22,10 +22,12 @@ TEST_DIRS += mochitest
XPIDLSRCS = \
nsIOpenWindowEventDetail.idl \
nsIAsyncScrollEventDetail.idl \
$(NULL)
EXPORTS = \
nsOpenWindowEventDetail.h \
nsAsyncScrollEventDetail.h \
$(NULL)
EXPORTS_NAMESPACES = mozilla
@ -35,6 +37,7 @@ EXPORTS_mozilla = \
CPPSRCS = \
nsOpenWindowEventDetail.cpp \
nsAsyncScrollEventDetail.cpp \
BrowserElementParent.cpp \
$(NULL)

View File

@ -0,0 +1,62 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsAsyncScrollEventDetail.h"
#include "nsDOMClassInfoID.h"
#include "nsIDOMClassInfo.h"
#include "nsIClassInfo.h"
#include "nsDOMClassInfo.h"
NS_IMPL_ADDREF(nsAsyncScrollEventDetail)
NS_IMPL_RELEASE(nsAsyncScrollEventDetail)
NS_INTERFACE_MAP_BEGIN(nsAsyncScrollEventDetail)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsIAsyncScrollEventDetail)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(AsyncScrollEventDetail)
NS_INTERFACE_MAP_END
DOMCI_DATA(AsyncScrollEventDetail, nsAsyncScrollEventDetail)
/* readonly attribute float top; */
NS_IMETHODIMP nsAsyncScrollEventDetail::GetTop(float *aTop)
{
*aTop = mTop;
return NS_OK;
}
/* readonly attribute float left; */
NS_IMETHODIMP nsAsyncScrollEventDetail::GetLeft(float *aLeft)
{
*aLeft = mLeft;
return NS_OK;
}
/* readonly attribute float width; */
NS_IMETHODIMP nsAsyncScrollEventDetail::GetWidth(float *aWidth)
{
*aWidth = mWidth;
return NS_OK;
}
/* readonly attribute float height; */
NS_IMETHODIMP nsAsyncScrollEventDetail::GetHeight(float *aHeight)
{
*aHeight = mHeight;
return NS_OK;
}
/* readonly attribute float scrollWidth; */
NS_IMETHODIMP nsAsyncScrollEventDetail::GetScrollWidth(float *aScrollWidth)
{
*aScrollWidth = mScrollWidth;
return NS_OK;
}
/* readonly attribute float scrollHeight; */
NS_IMETHODIMP nsAsyncScrollEventDetail::GetScrollHeight(float *aScrollHeight)
{
*aScrollHeight = mScrollHeight;
return NS_OK;
}

View File

@ -0,0 +1,36 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsIAsyncScrollEventDetail.h"
/**
* When we send a mozbrowserasyncscroll event (an instance of CustomEvent), we
* use an instance of this class as the event's detail.
*/
class nsAsyncScrollEventDetail : public nsIAsyncScrollEventDetail
{
public:
nsAsyncScrollEventDetail(const float left, const float top,
const float width, const float height,
const float contentWidth, const float contentHeigh)
: mTop(top)
, mLeft(left)
, mWidth(width)
, mHeight(height)
, mScrollWidth(contentWidth)
, mScrollHeight(contentHeigh)
{}
NS_DECL_ISUPPORTS
NS_DECL_NSIASYNCSCROLLEVENTDETAIL
private:
virtual ~nsAsyncScrollEventDetail() {}
const float mTop;
const float mLeft;
const float mWidth;
const float mHeight;
const float mScrollWidth;
const float mScrollHeight;
};

View File

@ -0,0 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
/**
* When we send a mozbrowserasyncscroll event (an instance of CustomEvent), we
* use an instance of this interface as the event's detail.
* [left, top, width, height]: The portion of the page which is currently
* visible onscreen in CSS pixels.
* [scrollWidth, scrollHeight]: The content width/height in CSS pixels.
*
* top + height may be larger than scrollHeight.
* This indicates that the content is over-scrolled, which occurs when the
* page "rubber-bands" after being scrolled all the way to the bottom.
* Similarly, left + width may be greater than scrollWidth,
* and both left and top may be negative.
*/
[scriptable, uuid(d0c13577-31e6-4701-b9b7-3535bbe19fe6)]
interface nsIAsyncScrollEventDetail : nsISupports
{
readonly attribute float top;
readonly attribute float left;
readonly attribute float width;
readonly attribute float height;
readonly attribute float scrollWidth;
readonly attribute float scrollHeight;
};

View File

@ -649,8 +649,10 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
CrashReporterParent* crashReporter =
static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("AppManifestURL"),
NS_ConvertUTF16toUTF8(mAppManifestURL));
crashReporter->GenerateCrashReport(this, NULL);
nsAutoString dumpID(crashReporter->ChildDumpID());
props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
#endif

View File

@ -136,8 +136,8 @@ MobileICCInfo.prototype = {
msisdn: null
};
function MobileVoicemailInfo() {}
MobileVoicemailInfo.prototype = {
function VoicemailInfo() {}
VoicemailInfo.prototype = {
number: null,
displayName: null
};
@ -319,7 +319,7 @@ function RILContentHelper() {
this.iccInfo = new MobileICCInfo();
this.voiceConnectionInfo = new MobileConnectionInfo();
this.dataConnectionInfo = new MobileConnectionInfo();
this.voicemailInfo = new MobileVoicemailInfo();
this.voicemailInfo = new VoicemailInfo();
this.initRequests();
this.initMessageListener(RIL_IPC_MSG_NAMES);
@ -336,7 +336,6 @@ function RILContentHelper() {
this.updateICCInfo(rilContext.icc, this.iccInfo);
this.updateConnectionInfo(rilContext.voice, this.voiceConnectionInfo);
this.updateConnectionInfo(rilContext.data, this.dataConnectionInfo);
this.updateVoicemailInfo(rilContext.voicemail, this.voicemailInfo);
}
RILContentHelper.prototype = {
@ -651,11 +650,25 @@ RILContentHelper.prototype = {
_enumerateTelephonyCallbacks: null,
voicemailStatus: null,
getVoicemailInfo: function getVoicemailInfo() {
// Get voicemail infomation by IPC only on first time.
this.getVoicemailInfo = function getVoicemailInfo() {
return this.voicemailInfo;
};
let voicemailInfo = cpmm.sendSyncMessage("RIL:GetVoicemailInfo")[0];
if (voicemailInfo) {
this.updateVoicemailInfo(voicemailInfo, this.voicemailInfo);
}
return this.voicemailInfo;
},
get voicemailNumber() {
return this.voicemailInfo.number;
return this.getVoicemailInfo().number;
},
get voicemailDisplayName() {
return this.voicemailInfo.displayName;
return this.getVoicemailInfo().displayName;
},
registerCallback: function registerCallback(callbackType, callback) {

View File

@ -99,7 +99,8 @@ const RIL_IPC_MOBILECONNECTION_MSG_NAMES = [
];
const RIL_IPC_VOICEMAIL_MSG_NAMES = [
"RIL:RegisterVoicemailMsg"
"RIL:RegisterVoicemailMsg",
"RIL:GetVoicemailInfo"
];
const RIL_IPC_CELLBROADCAST_MSG_NAMES = [
@ -204,8 +205,6 @@ function RadioInterfaceLayer() {
radioState: RIL.GECKO_RADIOSTATE_UNAVAILABLE,
cardState: RIL.GECKO_CARDSTATE_UNAVAILABLE,
icc: null,
voicemail: {number: null,
displayName: null},
// These objects implement the nsIDOMMozMobileConnectionInfo interface,
// although the actual implementation lives in the content process. So are
@ -229,6 +228,11 @@ function RadioInterfaceLayer() {
relSignalStrength: null},
};
this.voicemailInfo = {
number: null,
displayName: null
};
this.callWaitingStatus = null;
// Read the 'ril.radio.disabled' setting in order to start with a known
@ -479,6 +483,9 @@ RadioInterfaceLayer.prototype = {
case "RIL:RegisterCellBroadcastMsg":
this.registerMessageTarget("cellbroadcast", msg.target);
break;
case "RIL:GetVoicemailInfo":
// This message is sync.
return this.voicemailInfo;
}
},
@ -1576,12 +1583,12 @@ RadioInterfaceLayer.prototype = {
},
handleICCMbdn: function handleICCMbdn(message) {
let voicemail = this.rilContext.voicemail;
let voicemailInfo = this.voicemailInfo;
voicemail.number = message.number;
voicemail.displayName = message.alphaId;
voicemailInfo.number = message.number;
voicemailInfo.displayName = message.alphaId;
this._sendTargetMessage("voicemail", "RIL:VoicemailInfoChanged", voicemail);
this._sendTargetMessage("voicemail", "RIL:VoicemailInfoChanged", voicemailInfo);
},
handleICCInfoChange: function handleICCInfoChange(message) {

View File

@ -263,6 +263,14 @@ interface nsIICCRecords : nsISupports
readonly attribute jsval fdn;
};
[scriptable, uuid(c0c5cb9f-6372-4b5a-b74c-baacc2da5e4f)]
interface nsIVoicemailInfo : nsISupports
{
readonly attribute DOMString number;
readonly attribute DOMString displayName;
};
[scriptable, uuid(e6dc89f2-0d4e-46fc-902c-cfeeaee15e40)]
interface nsIRilContext : nsISupports
{
@ -277,7 +285,7 @@ interface nsIRilContext : nsISupports
readonly attribute nsIDOMMozMobileConnectionInfo data;
};
[scriptable, uuid(a90fef2c-44aa-4f2b-a0ee-a590e9dd345e)]
[scriptable, uuid(f9c586ee-71ce-4172-9b2e-d89f0ff9c6d9)]
interface nsIRadioInterfaceLayer : nsISupports
{
const unsigned short CALL_STATE_UNKNOWN = 0;
@ -300,6 +308,8 @@ interface nsIRadioInterfaceLayer : nsISupports
readonly attribute nsIRilContext rilContext;
readonly attribute nsIVoicemailInfo voicemailInfo;
/**
* PDP APIs
*/

View File

@ -5,4 +5,4 @@ qemu = true
[test_geolocation.js]
disabled = Bug 808783
[test_get_voicemailInfo.js]

View File

@ -0,0 +1,26 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 10000;
let Cc = SpecialPowers.Cc;
let Ci = SpecialPowers.Ci;
// Get system worker manager.
let systemWorkerManager = Cc["@mozilla.org/telephony/system-worker-manager;1"];
ok(systemWorkerManager);
// Get RadioIntefaceLayer interface.
let RIL = systemWorkerManager.getService(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIRadioInterfaceLayer);
ok(RIL);
// Check voicemail information accessible.
ok(RIL.voicemailInfo);
ok(RIL.voicemailInfo.number);
ok(RIL.voicemailInfo.displayName);
// These are the emulator's hard coded voicemail number and alphaId.
is(RIL.voicemailInfo.number, "+15552175049");
is(RIL.voicemailInfo.displayName, "Voicemail");
finish();

View File

@ -528,7 +528,8 @@ var interfaceNamesInGlobalScope =
"RTCPeerConnection",
"LocalMediaStream",
"CSSConditionRule",
"CSSGroupingRule"
"CSSGroupingRule",
"AsyncScrollEventDetail"
]
for (var i in SpecialPowers.Components.interfaces) {

View File

@ -0,0 +1,22 @@
/* -*- Mode: IDL; 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/.
*
* The origin of this IDL file is
* http://www.whatwg.org/specs/web-apps/current-work/#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements
* http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
* Opera Software ASA. You are granted a license to use, reproduce
* and create derivative works of this document.
*/
// http://www.whatwg.org/specs/web-apps/current-work/#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements
interface HTMLHeadingElement : HTMLElement {
/*};
// http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
partial interface HTMLHeadingElement {
*/
attribute DOMString align;
};

View File

@ -51,9 +51,11 @@ webidl_files = \
HTMLCollection.webidl \
HTMLDataListElement.webidl \
HTMLDivElement.webidl \
HTMLDocument.webidl \
HTMLElement.webidl \
HTMLFontElement.webidl \
HTMLFrameSetElement.webidl \
HTMLHeadingElement.webidl \
HTMLLabelElement.webidl \
HTMLOptionsCollection.webidl \
HTMLPropertiesCollection.webidl \

View File

@ -92,11 +92,18 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
mMonitor("AsyncPanZoomController"),
mLastSampleTime(TimeStamp::Now()),
mState(NOTHING),
mLastAsyncScrollTime(TimeStamp::Now()),
mLastAsyncScrollOffset(0, 0),
mCurrentAsyncScrollOffset(0, 0),
mAsyncScrollTimeoutTask(nullptr),
mAsyncScrollThrottleTime(100),
mAsyncScrollTimeout(300),
mDPI(72),
mWaitingForContentToPaint(false),
mDisableNextTouchBatch(false),
mHandlingTouchQueue(false)
{
MOZ_ASSERT(NS_IsMainThread());
if (aGestures == USE_GESTURE_DETECTOR) {
mGestureEventListener = new GestureEventListener(this);
}
@ -109,6 +116,9 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
ClearOnShutdown(&gComputedTimingFunction);
}
Preferences::GetUint("apzc.asyncscroll.throttle", &mAsyncScrollThrottleTime);
Preferences::GetUint("apzc.asyncscroll.timeout", &mAsyncScrollTimeout);
}
AsyncPanZoomController::~AsyncPanZoomController() {
@ -367,6 +377,11 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
return nsEventStatus_eIgnore;
}
{
MonitorAutoLock monitor(mMonitor);
SendAsyncScrollEvent();
}
switch (mState) {
case FLING:
// Should never happen.
@ -679,6 +694,7 @@ bool AsyncPanZoomController::DoFling(const TimeDuration& aDelta) {
// Bring the resolution back in sync with the zoom, in case we scaled down
// the zoom while accelerating.
SetZoomAndResolution(mFrameMetrics.mZoom.width);
SendAsyncScrollEvent();
RequestContentRepaint();
mState = NOTHING;
return false;
@ -953,6 +969,8 @@ void AsyncPanZoomController::RequestContentRepaint() {
return;
}
SendAsyncScrollEvent();
// Cache the zoom since we're temporarily changing it for
// acceleration-scaled painting.
gfxFloat actualZoom = mFrameMetrics.mZoom.width;
@ -979,6 +997,16 @@ void AsyncPanZoomController::RequestContentRepaint() {
mFrameMetrics.mZoom = gfxSize(actualZoom, actualZoom);
}
void
AsyncPanZoomController::FireAsyncScrollOnTimeout()
{
if (mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
MonitorAutoLock monitor(mMonitor);
SendAsyncScrollEvent();
}
mAsyncScrollTimeoutTask = nullptr;
}
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
ContainerLayer* aLayer,
ViewTransform* aNewTransform) {
@ -1036,6 +1064,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
// Bring the resolution in sync with the zoom.
SetZoomAndResolution(mFrameMetrics.mZoom.width);
mState = NOTHING;
SendAsyncScrollEvent();
RequestContentRepaint();
}
@ -1056,6 +1085,34 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
}
scrollOffset = gfxPoint(mFrameMetrics.mScrollOffset.x, mFrameMetrics.mScrollOffset.y);
mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset;
}
// Cancel the mAsyncScrollTimeoutTask because we will fire a
// mozbrowserasyncscroll event or renew the mAsyncScrollTimeoutTask again.
if (mAsyncScrollTimeoutTask) {
mAsyncScrollTimeoutTask->Cancel();
mAsyncScrollTimeoutTask = nullptr;
}
// Fire the mozbrowserasyncscroll event immediately if it's been
// sAsyncScrollThrottleTime ms since the last time we fired the event and the
// current scroll offset is different than the mLastAsyncScrollOffset we sent
// with the last event.
// Otherwise, start a timer to fire the event sAsyncScrollTimeout ms from now.
TimeDuration delta = aSampleTime - mLastAsyncScrollTime;
if (delta.ToMilliseconds() > mAsyncScrollThrottleTime &&
mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
MonitorAutoLock monitor(mMonitor);
mLastAsyncScrollTime = aSampleTime;
mLastAsyncScrollOffset = mCurrentAsyncScrollOffset;
SendAsyncScrollEvent();
}
else {
mAsyncScrollTimeoutTask =
NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout);
MessageLoop::current()->PostDelayedTask(FROM_HERE,
mAsyncScrollTimeoutTask,
mAsyncScrollTimeout);
}
nsIntPoint scrollCompensation(
@ -1312,5 +1369,22 @@ void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
mMaxZoom = aMaxZoom;
}
void AsyncPanZoomController::SendAsyncScrollEvent() {
if (!mGeckoContentController) {
return;
}
gfx::Rect contentRect;
gfx::Size scrollableSize;
{
scrollableSize = gfx::Size(mFrameMetrics.mScrollableRect.width,
mFrameMetrics.mScrollableRect.height);
contentRect =
AsyncPanZoomController::CalculateCompositedRectInCssPixels(mFrameMetrics);
contentRect.MoveTo(mCurrentAsyncScrollOffset);
}
mGeckoContentController->SendAsyncScrollDOMEvent(contentRect, scrollableSize);
}
}
}

View File

@ -227,6 +227,12 @@ public:
static gfx::Rect CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics);
/**
* Send an mozbrowserasyncscroll event.
* *** The monitor must be held while calling this.
*/
void SendAsyncScrollEvent();
protected:
/**
* Internal handler for ReceiveInputEvent(). Does all the actual work.
@ -439,6 +445,14 @@ protected:
*/
void SetZoomAndResolution(float aScale);
/**
* Timeout function for mozbrowserasyncscroll event. Because we throttle
* mozbrowserasyncscroll events in some conditions, this function ensures
* that the last mozbrowserasyncscroll event will be fired after a period of
* time.
*/
void FireAsyncScrollOnTimeout();
private:
enum PanZoomState {
NOTHING, /* no touch-start events received */
@ -532,6 +546,27 @@ private:
// previous paints.
TimeStamp mPreviousPaintStartTime;
// The last time and offset we fire the mozbrowserasyncscroll event when
// compositor has sampled the content transform for this frame.
TimeStamp mLastAsyncScrollTime;
gfx::Point mLastAsyncScrollOffset;
// The current offset drawn on the screen, it may not be sent since we have
// throttling policy for mozbrowserasyncscroll event.
gfx::Point mCurrentAsyncScrollOffset;
// The delay task triggered by the throttling mozbrowserasyncscroll event
// ensures the last mozbrowserasyncscroll event is always been fired.
CancelableTask* mAsyncScrollTimeoutTask;
// The time period in ms that throttles mozbrowserasyncscroll event.
// Default is 100ms if there is no "apzc.asyncscroll.throttle" in preference.
uint32_t mAsyncScrollThrottleTime;
// The timeout in ms for mAsyncScrollTimeoutTask delay task.
// Default is 300ms if there is no "apzc.asyncscroll.timeout" in preference.
uint32_t mAsyncScrollTimeout;
int mDPI;
// Stores the current paint status of the frame that we're managing. Repaints

View File

@ -44,6 +44,14 @@ public:
*/
virtual void HandleLongTap(const nsIntPoint& aPoint) = 0;
/**
* Requests sending a mozbrowserasyncscroll domevent to embedder.
* |aContentRect| is in CSS pixels, relative to the current cssPage.
* |aScrollableSize| is the current content width/height in CSS pixels.
*/
virtual void SendAsyncScrollDOMEvent(const gfx::Rect &aContentRect,
const gfx::Size &aScrollableSize) = 0;
GeckoContentController() {}
virtual ~GeckoContentController() {}
};

View File

@ -364,7 +364,8 @@ ArrayConcatDense(JSContext *cx, HandleObject obj1, HandleObject obj2, HandleObje
bool
CharCodeAt(JSContext *cx, HandleString str, int32_t index, uint32_t *code)
{
JS_ASSERT(index < str->length());
JS_ASSERT(index >= 0 &&
static_cast<uint32_t>(index) < str->length());
const jschar *chars = str->getChars(cx);
if (!chars)

View File

@ -133,19 +133,6 @@ members = [
'nsIDOMHTMLButtonElement.value',
'nsIDOMHTMLButtonElement.disabled',
'nsIDOMHTMLCommandElement.*',
'nsIDOMHTMLDocument.body',
'nsIDOMHTMLDocument.getElementsByName',
'nsIDOMHTMLDocument.anchors',
'nsIDOMHTMLDocument.links',
'nsIDOMHTMLDocument.forms',
'nsIDOMHTMLDocument.cookie',
'nsIDOMHTMLDocument.images',
'nsIDOMHTMLDocument.write',
'nsIDOMHTMLDocument.writeln',
'nsIDOMHTMLDocument.domain',
'nsIDOMHTMLDocument.getSelection',
'nsIDOMHTMLDocument.designMode',
'nsIDOMHTMLDocument.head',
'nsIDOMHTMLFormElement.elements',
'nsIDOMHTMLFormElement.name',
'nsIDOMHTMLFormElement.submit',
@ -372,13 +359,11 @@ customIncludes = [
'nsIContent.h',
'nsIDocument.h',
'nsCSSPropertiesQS.h',
'nsDocument.h',
'nsDOMTokenList.h',
'nsGenericDOMDataNode.h',
'mozilla/dom/Element.h',
'nsGenericHTMLElement.h',
'nsSVGElement.h',
'nsHTMLDocument.h',
'nsDOMQS.h',
'nsDOMStringMap.h',
'HTMLPropertiesCollection.h',
@ -390,6 +375,7 @@ customIncludes = [
'mozilla/dom/DocumentBinding.h',
'mozilla/dom/SVGElementBinding.h',
'nsPerformance.h',
'mozilla/dom/HTMLDocumentBinding.h',
]
customReturnInterfaces = [
@ -397,21 +383,6 @@ customReturnInterfaces = [
'nsIDOMCanvasGradient',
]
nsIDOMHTMLDocument_Write_customMethodCallCode = """
nsAString &str = arg0;
for (unsigned i = 1; i < argc; ++i) {
xpc_qsDOMString next_arg(cx, argv[i], &argv[i],
xpc_qsDOMString::eStringify,
xpc_qsDOMString::eStringify);
if (!next_arg.IsValid())
return JS_FALSE;
str.Append(next_arg);
}
rv = self->%s(arg0, cx);
"""
nsIDOMStorage_Clear_customMethodCallCode = """
rv = self->Clear();
if (NS_SUCCEEDED(rv))
@ -419,33 +390,6 @@ nsIDOMStorage_Clear_customMethodCallCode = """
"""
customMethodCalls = {
'nsIDOMHTMLDocument_': {
'thisType': 'nsHTMLDocument'
},
'nsIDOMHTMLDocument_Write': {
'thisType': 'nsHTMLDocument',
'code': nsIDOMHTMLDocument_Write_customMethodCallCode % 'Write'
},
'nsIDOMHTMLDocument_Writeln': {
'thisType': 'nsHTMLDocument',
'code': nsIDOMHTMLDocument_Write_customMethodCallCode % 'Writeln'
},
'nsIDOMHTMLDocument_GetBody': {
'thisType': 'nsHTMLDocument',
'code': ' nsIContent *result = self->GetBody();',
'canFail': False
},
'nsIDOMHTMLDocument_GetHead': {
'thisType': 'nsHTMLDocument',
'code': ' nsIContent *result = self->GetHead();',
'canFail': False
},
'nsIDOMHTMLDocument_GetElementsByName': {
'thisType': 'nsHTMLDocument',
'code': ' nsRefPtr<nsContentList> result = '
'self->GetElementsByName(arg0);',
'canFail': False
},
'nsIDOMStorage_Clear': {
'code': nsIDOMStorage_Clear_customMethodCallCode
},
@ -486,5 +430,6 @@ newBindingProperties = {
'nsIDOMElement': 'mozilla::dom::ElementBinding::sNativePropertyHooks.mNativeProperties.regular',
'nsIDOMHTMLElement': 'mozilla::dom::HTMLElementBinding::sNativePropertyHooks.mNativeProperties.regular',
'nsIDOMDocument': 'mozilla::dom::DocumentBinding::sNativePropertyHooks.mNativeProperties.regular',
'nsIDOMSVGElement': 'mozilla::dom::SVGElementBinding::sNativePropertyHooks.mNativeProperties.regular'
'nsIDOMSVGElement': 'mozilla::dom::SVGElementBinding::sNativePropertyHooks.mNativeProperties.regular',
'nsIDOMHTMLDocument': 'mozilla::dom::HTMLDocumentBinding::sNativePropertyHooks.mNativeProperties.regular',
}

View File

@ -8,6 +8,7 @@
/* rendering object for CSS "display: flex" */
#include "nsFlexContainerFrame.h"
#include "nsContentUtils.h"
#include "nsDisplayList.h"
#include "nsLayoutUtils.h"
#include "nsPresContext.h"
@ -222,46 +223,6 @@ private:
AxisOrientationType mCrossAxis;
};
// Encapsulates a frame for a flex item, with enough information for us to
// sort by 'order' (and by the frame's actual index inside the parent's
// child-frames array, among frames with the same 'order').
class SortableFrame {
public:
SortableFrame(nsIFrame* aFrame,
int32_t aOrderValue,
uint32_t aIndexInFrameList)
: mFrame(aFrame),
mOrderValue(aOrderValue),
mIndexInFrameList(aIndexInFrameList)
{
MOZ_ASSERT(aFrame, "expecting a non-null child frame");
}
// Implement operator== and operator< so that we can use nsDefaultComparator
bool operator==(const SortableFrame& rhs) const {
MOZ_ASSERT(mFrame != rhs.mFrame ||
(mOrderValue == rhs.mOrderValue &&
mIndexInFrameList == rhs.mIndexInFrameList),
"if frames are equal, the other member data should be too");
return mFrame == rhs.mFrame;
}
bool operator<(const SortableFrame& rhs) const {
if (mOrderValue == rhs.mOrderValue) {
return mIndexInFrameList < rhs.mIndexInFrameList;
}
return mOrderValue < rhs.mOrderValue;
}
// Accessor for the frame
inline nsIFrame* Frame() const { return mFrame; }
protected:
nsIFrame* const mFrame; // The flex item's frame
int32_t const mOrderValue; // mFrame's computed value of 'order' property
uint32_t const mIndexInFrameList; // mFrame's idx in parent's child frames
};
// Represents a flex item.
// Includes the various pieces of input that the Flexbox Layout Algorithm uses
// to resolve a flexible width.
@ -490,6 +451,101 @@ protected:
// in our constructor).
};
/**
* Helper-function to find the nsIContent* that we should use for comparing the
* DOM tree position of the given flex-item frame.
*
* In most cases, this will be aFrame->GetContent(), but if aFrame is an
* anonymous container, then its GetContent() won't be what we want. In such
* cases, we need to find aFrame's first non-anonymous-container descendant.
*/
static nsIContent*
GetContentForComparison(const nsIFrame* aFrame)
{
MOZ_ASSERT(aFrame, "null frame passed to GetContentForComparison()");
MOZ_ASSERT(aFrame->IsFlexItem(), "only intended for flex items");
while (true) {
nsIAtom* pseudoTag = aFrame->GetStyleContext()->GetPseudo();
// If aFrame isn't an anonymous container, then it'll do.
if (!pseudoTag || // No pseudotag.
!nsCSSAnonBoxes::IsAnonBox(pseudoTag) || // Pseudotag isn't anon.
pseudoTag == nsCSSAnonBoxes::mozNonElement) { // Text, not a container.
return aFrame->GetContent();
}
// Otherwise, descend to its first child and repeat.
aFrame = aFrame->GetFirstPrincipalChild();
MOZ_ASSERT(aFrame, "why do we have an anonymous box without any children?");
}
}
/**
* Sorting helper-function that compares two frames' "order" property-values,
* and if they're equal, compares the DOM positions of their corresponding
* content nodes. Returns true if aFrame1 is "less than or equal to" aFrame2
* according to this comparison.
*
* Note: This can't be a static function, because we need to pass it as a
* template argument. (Only functions with external linkage can be passed as
* template arguments.)
*
* @return true if the computed "order" property of aFrame1 is less than that
* of aFrame2, or if the computed "order" values are equal and aFrame1's
* corresponding DOM node is earlier than aFrame2's in the DOM tree.
* Otherwise, returns false.
*/
bool
IsOrderLEQWithDOMFallback(nsIFrame* aFrame1,
nsIFrame* aFrame2)
{
if (aFrame1 == aFrame2) {
// Anything is trivially LEQ itself, so we return "true" here... but it's
// probably bad if we end up actually needing this, so let's assert.
NS_ERROR("Why are we checking if a frame is LEQ itself?");
return true;
}
int32_t order1 = aFrame1->GetStylePosition()->mOrder;
int32_t order2 = aFrame2->GetStylePosition()->mOrder;
if (order1 != order2) {
return order1 < order2;
}
// Same "order" value --> use DOM position.
nsIContent* content1 = GetContentForComparison(aFrame1);
nsIContent* content2 = GetContentForComparison(aFrame2);
MOZ_ASSERT(content1 != content2,
"Two different flex items are using the same nsIContent node for "
"comparison, so we may be sorting them in an arbitrary order");
return nsContentUtils::PositionIsBefore(content1, content2);
}
/**
* Sorting helper-function that compares two frames' "order" property-values.
* Returns true if aFrame1 is "less than or equal to" aFrame2 according to this
* comparison.
*
* Note: This can't be a static function, because we need to pass it as a
* template argument. (Only functions with external linkage can be passed as
* template arguments.)
*
* @return true if the computed "order" property of aFrame1 is less than or
* equal to that of aFrame2. Otherwise, returns false.
*/
bool
IsOrderLEQ(nsIFrame* aFrame1,
nsIFrame* aFrame2)
{
int32_t order1 = aFrame1->GetStylePosition()->mOrder;
int32_t order2 = aFrame2->GetStylePosition()->mOrder;
return order1 <= order2;
}
bool
nsFlexContainerFrame::IsHorizontal()
{
@ -564,14 +620,9 @@ nsFlexContainerFrame::AppendFlexItemForChild(
"We gave flex item unconstrained available height, so it "
"should be complete");
// Call DidReflow to clear NS_FRAME_IN_REFLOW and any other state on the
// child before our next ReflowChild call.
// NOTE: We're intentionally calling DidReflow() instead of the wrapper
// FinishReflowChild() because we don't want the rest of the stuff in
// FinishReflowChild() (e.g. moving the frame's rect) to happen until we
// do our "real" reflow of the child.
rv = aChildFrame->DidReflow(aPresContext, &childRSForMeasuringHeight,
nsDidReflowStatus::FINISHED);
rv = FinishReflowChild(aChildFrame, aPresContext,
&childRSForMeasuringHeight, childDesiredSize,
0, 0, 0);
NS_ENSURE_SUCCESS(rv, rv);
// Subtract border/padding in vertical axis, to get _just_
@ -940,6 +991,18 @@ nsFlexContainerFrame::~nsFlexContainerFrame()
{
}
template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
/* static */ bool
nsFlexContainerFrame::SortChildrenIfNeeded()
{
if (nsLayoutUtils::IsFrameListSorted<IsLessThanOrEqual>(mFrames)) {
return false;
}
nsLayoutUtils::SortFrameList<IsLessThanOrEqual>(mFrames);
return true;
}
/* virtual */
nsIAtom*
nsFlexContainerFrame::GetType() const
@ -978,6 +1041,9 @@ nsFlexContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
MOZ_ASSERT(nsLayoutUtils::IsFrameListSorted<IsOrderLEQWithDOMFallback>(mFrames),
"Frame list should've been sorted in reflow");
nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
NS_ENSURE_SUCCESS(rv, rv);
@ -1300,25 +1366,6 @@ nsFlexContainerFrame::ResolveFlexibleLengths(
#endif // DEBUG
}
void
BuildSortedChildArray(const nsFrameList& aChildren,
nsTArray<SortableFrame>& aSortedChildren)
{
aSortedChildren.SetCapacity(aChildren.GetLength());
// Throw all our children in the array...
uint32_t indexInFrameList = 0;
for (nsFrameList::Enumerator e(aChildren); !e.AtEnd(); e.Next()) {
int32_t orderValue = e.get()->GetStylePosition()->mOrder;
aSortedChildren.AppendElement(SortableFrame(e.get(), orderValue,
indexInFrameList));
indexInFrameList++;
}
// ... and sort (by 'order' property)
aSortedChildren.Sort();
}
MainAxisPositionTracker::
MainAxisPositionTracker(nsFlexContainerFrame* aFlexContainerFrame,
const FlexboxAxisTracker& aAxisTracker,
@ -1787,18 +1834,11 @@ nsFlexContainerFrame::GenerateFlexItems(
{
MOZ_ASSERT(aFlexItems.IsEmpty(), "Expecting outparam to start out empty");
// Sort by 'order' property:
nsTArray<SortableFrame> sortedChildren;
BuildSortedChildArray(mFrames, sortedChildren);
// Build list of unresolved flex items:
// XXXdholbert When we support multi-line, we might want this to be a linked
// list, so we can easily split into multiple lines.
aFlexItems.SetCapacity(sortedChildren.Length());
for (uint32_t i = 0; i < sortedChildren.Length(); ++i) {
nsresult rv = AppendFlexItemForChild(aPresContext,
sortedChildren[i].Frame(),
aFlexItems.SetCapacity(mFrames.GetLength());
for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
nsresult rv = AppendFlexItemForChild(aPresContext, e.get(),
aReflowState, aAxisTracker,
aFlexItems);
NS_ENSURE_SUCCESS(rv,rv);
@ -1998,6 +2038,22 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
bool shouldReflowChildren =
NS_SUBTREE_DIRTY(this) || aReflowState.ShouldReflowAllKids();
// If we've never reordered our children, then we can trust that they're
// already in DOM-order, and we only need to consider their "order" property
// when checking them for sortedness & sorting them.
//
// After we actually sort them, though, we can't trust that they're in DOM
// order anymore. So, from that point on, our sort & sorted-order-checking
// operations need to use a fancier LEQ function that also takes DOM order
// into account, so that we can honor the spec's requirement that frames w/
// equal "order" values are laid out in DOM order.
if (!mChildrenHaveBeenReordered) {
mChildrenHaveBeenReordered =
SortChildrenIfNeeded<IsOrderLEQ>();
} else {
SortChildrenIfNeeded<IsOrderLEQWithDOMFallback>();
}
const FlexboxAxisTracker axisTracker(this);
// Generate a list of our flex items (already sorted), and get our main
@ -2142,6 +2198,8 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
if (IsAxisHorizontal(axisTracker.GetCrossAxis())) {
childReflowState.SetComputedWidth(curItem.GetCrossSize());
} else {
// If this item's height is stretched, it's a relative height.
curItem.Frame()->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
childReflowState.SetComputedHeight(curItem.GetCrossSize());
}
}

View File

@ -61,10 +61,23 @@ protected:
nsFlexContainerFrame(nsStyleContext* aContext) :
nsFlexContainerFrameSuper(aContext),
mCachedContentBoxCrossSize(nscoord_MIN),
mCachedAscent(nscoord_MIN)
mCachedAscent(nscoord_MIN),
mChildrenHaveBeenReordered(false)
{}
virtual ~nsFlexContainerFrame();
/**
* Checks whether our child-frame list "mFrames" is sorted, using the given
* IsLessThanOrEqual function, and sorts it if it's not already sorted.
*
* XXXdholbert Once we support pagination, we need to make this function
* check our continuations as well (or wrap it in a function that does).
*
* @return true if we had to sort mFrames, false if it was already sorted.
*/
template<bool IsLessThanOrEqual(nsIFrame*, nsIFrame*)>
bool SortChildrenIfNeeded();
// Protected flex-container-specific methods / member-vars
#ifdef DEBUG
void SanityCheckAnonymousFlexItems() const;
@ -113,6 +126,8 @@ protected:
// reflows where we're not dirty:
nscoord mCachedContentBoxCrossSize; // Cross size of our content-box.
nscoord mCachedAscent; // Our ascent, in prev. reflow.
bool mChildrenHaveBeenReordered; // Have we ever had to reorder our kids
// to satisfy their 'order' values?
};
#endif /* nsFlexContainerFrame_h___ */

View File

@ -13,6 +13,7 @@
#ifdef MOZ_ENABLE_D3D9_LAYER
# include "LayerManagerD3D9.h"
#endif //MOZ_ENABLE_D3D9_LAYER
#include "mozilla/BrowserElementParent.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/layers/AsyncPanZoomController.h"
#include "mozilla/layers/CompositorParent.h"
@ -550,6 +551,24 @@ public:
void ClearRenderFrame() { mRenderFrame = nullptr; }
virtual void SendAsyncScrollDOMEvent(const gfx::Rect& aContentRect,
const gfx::Size& aContentSize) MOZ_OVERRIDE
{
if (MessageLoop::current() != mUILoop) {
mUILoop->PostTask(
FROM_HERE,
NewRunnableMethod(this,
&RemoteContentController::SendAsyncScrollDOMEvent,
aContentRect, aContentSize));
return;
}
if (mRenderFrame) {
TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect,
aContentSize);
}
}
private:
void DoRequestContentRepaint(const FrameMetrics& aFrameMetrics)
{

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
#container {
display: flex;
width: 100px;
height: 100px;
background: lime;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!--
This test checks that we reflow sufficiently when a grandchild of a
flex container needs an incremental reflow. This test should end up
rendering as a lime square, 100px by 100px.
-->
<html xmlns="http://www.w3.org/1999/xhtml"
class="reftest-wait">
<head>
<style>
#container {
display: flex;
flex-direction: column;
width: 100px;
}
#item {
background: red;
}
#tweakMe {
height: 100px;
background: orange;
padding-left: 1px;
}
</style>
<script>
function tweak() {
var tweakMe = document.getElementById("tweakMe");
tweakMe.style.paddingLeft = "0";
tweakMe.style.background = "lime";
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", tweak, false);
</script>
</head>
<body>
<div id="container">
<div id="item">
<div id="tweakMe"></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!--
This test checks that we reflow sufficiently when a stretched, nested
flex container needs an incremental reflow. This test should end up
rendering as a lime square, 100px by 100px.
-->
<html xmlns="http://www.w3.org/1999/xhtml"
class="reftest-wait">
<head>
<style>
#outerContainer {
display: flex;
width: 100px;
height: 100px;
background: red;
}
#tweakMe {
display: flex;
background: orange;
width: 100px;
/* height should stretch to fill parent's height, via
* parent's "align-items: stretch" (the default) */
padding-left: 1px;
}
</style>
<script>
function tweak() {
var tweakMe = document.getElementById("tweakMe");
tweakMe.style.paddingLeft = "0";
tweakMe.style.background = "lime";
document.documentElement.removeAttribute("class");
}
window.addEventListener("MozReftestInvalidate", tweak, false);
</script>
</head>
<body>
<div id="outerContainer">
<div id="tweakMe"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- Reference case for flex items containing overlapping content.
This reference uses inline-block in place of inline-flex, with floated
children in place of flex items, and with hardcoded DOM-reordering in
place of "order" reordering. -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
body {
line-height: 0;
}
.flexbox {
display: inline-block;
width: 20px;
height: 10px;
border: 2px solid gray;
margin-bottom: 10px;
margin-right: 10px;
}
.a {
width: 10px;
height: 10px;
background: lightblue;
float: left; /* to stack horizontally, like a flex item */
}
.b {
width: 10px;
height: 10px;
background: pink;
float: left; /* to stack horizontally, like a flex item */
}
.aKid {
margin-left: 3px;
margin-top: 3px;
width: 10px;
height: 10px;
background: steelblue;
border: 1px solid blue;
}
.bKid {
margin-left: 3px;
margin-top: 6px;
width: 10px;
height: 10px;
background: violet;
border: 1px solid purple;
}
/* Need to set 'position' for z-index to take effect. */
.zn2 { z-index: -2; position: relative; }
.zn1 { z-index: -1; position: relative; }
.z0 { z-index: 0; position: relative; }
.z1 { z-index: 1; position: relative; }
</style>
</head>
<body>
<!-- order not set: -->
<div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div>
<br/>
<!-- order set, but it matches content order, so it shouldn't matter: -->
<div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div>
<br/>
<!-- order set to reverse of content-order: -->
<div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div
><div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div
><div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div
><div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div>
<br/>
<!-- order set to reverse of content-order, AND with z-index set on
one or both items, but not such that it changes the paint order -->
<div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div
><div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div
><div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div
><div class="flexbox">
<div class="b"><div class="bKid"/></div>
<div class="a"><div class="aKid"/></div>
</div>
<br/>
<!-- order set to reverse of content-order, AND with z-index set on
one or both items, in such a way that it affects paint order -->
<div class="flexbox">
<!-- 'a' is behind the container's border -->
<div class="b"><div class="bKid"/></div>
<div class="a zn1"><div class="aKid"/></div>
</div
><div class="flexbox">
<!-- 'a' and 'b' are both behind the container's border -->
<div class="b zn1"><div class="bKid"/></div>
<div class="a zn1"><div class="aKid"/></div>
</div
><div class="flexbox">
<!-- 'a' and 'b' are both behind the container's border,
and 'a' is behind 'b' despite coming after it in the 'order'
ordering-->
<div class="b zn1"><div class="bKid"/></div>
<div class="a zn2"><div class="aKid"/></div>
</div
><div class="flexbox">
<!-- 'a' and 'b' are both in front of the container's border,
and 'a' is behind 'b' despite coming after it in the 'order'
ordering-->
<div class="b z1"><div class="bKid"/></div>
<div class="a z0"><div class="aKid"/></div>
</div>
</body>
</html>

View File

@ -0,0 +1,172 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!-- Testcase with flex items containing overlapping content, with
"order" and "z-index" set on some of them, to test how that affects
paint-order. -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
body {
line-height: 0;
}
.flexbox {
display: inline-flex;
width: 20px;
height: 10px;
border: 2px solid gray;
margin-bottom: 10px;
margin-right: 10px;
}
.a {
width: 10px;
height: 10px;
background: lightblue;
min-width: 0;
}
.b {
width: 10px;
height: 10px;
background: pink;
min-width: 0;
}
.aKid {
margin-left: 3px;
margin-top: 3px;
width: 10px;
height: 10px;
background: steelblue;
border: 1px solid blue;
}
.bKid {
margin-left: 3px;
margin-top: 6px;
width: 10px;
height: 10px;
background: violet;
border: 1px solid purple;
}
.on1 { order: -1; }
.o0 { order: 0; }
.o1 { order: 1; }
.o2 { order: 2; }
.zn2 { z-index: -2; }
.zn1 { z-index: -1; }
.z0 { z-index: 0; }
.z1 { z-index: 1; }
</style>
</head>
<body>
<!-- order not set: -->
<div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div>
<br/>
<!-- order set, but it matches content order, so it shouldn't matter: -->
<div class="flexbox">
<div class="a on1"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o0"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o0"><div class="aKid"/></div>
<div class="b o0"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o2"><div class="aKid"/></div>
<div class="b o2"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b o0"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b o1"><div class="bKid"/></div>
</div>
<br/>
<!-- order set to reverse of content-order: -->
<div class="flexbox">
<div class="a o1"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a"><div class="aKid"/></div>
<div class="b on1"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o0"><div class="aKid"/></div>
<div class="b on1"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o2"><div class="aKid"/></div>
<div class="b o1"><div class="bKid"/></div>
</div>
<br/>
<!-- order set to reverse of content-order, AND with z-index set on
one or both items, but not such that it changes the paint order -->
<div class="flexbox">
<div class="a o1 z0"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o1 z1"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o1 z0"><div class="aKid"/></div>
<div class="b z0"><div class="bKid"/></div>
</div
><div class="flexbox">
<div class="a o1 z1"><div class="aKid"/></div>
<div class="b z0"><div class="bKid"/></div>
</div>
<br/>
<!-- order set to reverse of content-order, AND with z-index set on
one or both items, in such a way that it affects paint order -->
<div class="flexbox">
<!-- 'a' is behind the container's border -->
<div class="a o1 zn1"><div class="aKid"/></div>
<div class="b"><div class="bKid"/></div>
</div
><div class="flexbox">
<!-- 'a' and 'b' are both behind the container's border -->
<div class="a o1 zn1"><div class="aKid"/></div>
<div class="b zn1"><div class="bKid"/></div>
</div
><div class="flexbox">
<!-- 'a' and 'b' are both behind the container's border,
and 'a' is behind 'b' despite coming after it in the 'order'
ordering-->
<div class="a o1 zn2"><div class="aKid"/></div>
<div class="b zn1"><div class="bKid"/></div>
</div
><div class="flexbox">
<!-- 'a' and 'b' are both in front of the container's border,
and 'a' is behind 'b' despite coming after it in the 'order'
ordering-->
<div class="a o1 z0"><div class="aKid"/></div>
<div class="b z1"><div class="bKid"/></div>
</div>
</body>
</html>

View File

@ -58,7 +58,11 @@ fails == flexbox-basic-img-vert-2.xhtml flexbox-basic-img-vert-2-ref.xhtml # bug
== flexbox-basic-video-vert-1.xhtml flexbox-basic-video-vert-1-ref.xhtml
fails == flexbox-basic-video-vert-2.xhtml flexbox-basic-video-vert-2-ref.xhtml # bug 794660
# Tests for dynamic modifications to flexboxes
# Tests for dynamic modifications of content inside a flex container
== flexbox-dyn-changePadding-1a.xhtml flexbox-dyn-changePadding-1-ref.xhtml
== flexbox-dyn-changePadding-1b.xhtml flexbox-dyn-changePadding-1-ref.xhtml
# Tests for dynamic insertions of content into a flex container
# (with existing [div | span | text] inside the flexbox, and new content
# inserted adjacent to that existing content.)
== flexbox-dyn-insertAroundDiv-1.xhtml flexbox-dyn-insertAroundDiv-1-ref.xhtml
@ -97,6 +101,7 @@ fails == flexbox-basic-video-vert-2.xhtml flexbox-basic-video-vert-2-ref.xhtml #
# Tests for the order in which we paint flex items
== flexbox-paint-ordering-1.xhtml flexbox-paint-ordering-1-ref.xhtml
== flexbox-paint-ordering-2.xhtml flexbox-paint-ordering-2-ref.xhtml
# Tests for handling of absolutely/fixed/relatively-positioned flex items.
== flexbox-position-absolute-1.xhtml flexbox-position-absolute-1-ref.xhtml

View File

@ -1299,6 +1299,9 @@ nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent,
mNoneBits(0),
mRefCnt(0)
{
NS_ABORT_IF_FALSE(IsRoot() == !aRule,
"non-root rule nodes must have a rule");
mChildren.asVoid = nullptr;
MOZ_COUNT_CTOR(nsRuleNode);
NS_IF_ADDREF(mRule);

View File

@ -270,10 +270,10 @@ nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
break;
}
nsStyleSet::RuleAndLevel* curRule = rules.AppendElement();
curRule->mLevel = ruleNode->GetLevel();
nsStyleSet::RuleAndLevel curRule;
curRule.mLevel = ruleNode->GetLevel();
if (curRule->mLevel == nsStyleSet::eAnimationSheet) {
if (curRule.mLevel == nsStyleSet::eAnimationSheet) {
ElementAnimations* ea =
mPresContext->AnimationManager()->GetElementAnimations(aElement,
oldStyle->GetPseudoType(),
@ -281,20 +281,24 @@ nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
NS_ASSERTION(ea, "Rule has level eAnimationSheet without animation on manager");
mPresContext->AnimationManager()->EnsureStyleRuleFor(ea);
curRule->mRule = ea->mStyleRule;
curRule.mRule = ea->mStyleRule;
ForceLayerRerendering(primaryFrame, ea);
} else if (curRule->mLevel == nsStyleSet::eTransitionSheet) {
} else if (curRule.mLevel == nsStyleSet::eTransitionSheet) {
ElementTransitions *et =
GetElementTransitions(aElement, oldStyle->GetPseudoType(), false);
NS_ASSERTION(et, "Rule has level eTransitionSheet without transition on manager");
et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh());
curRule->mRule = et->mStyleRule;
curRule.mRule = et->mStyleRule;
ForceLayerRerendering(primaryFrame, et);
} else {
curRule->mRule = ruleNode->GetRule();
curRule.mRule = ruleNode->GetRule();
}
if (curRule.mRule) {
rules.AppendElement(curRule);
}
} while ((ruleNode = ruleNode->GetParent()));
@ -329,7 +333,6 @@ nsTransitionManager::UpdateThrottledStylesForSubtree(nsIContent* aContent,
newStyle = UpdateThrottledStyle(element, aParentStyle);
// remove the current transition from the working set
et->mFlushGeneration = mPresContext->RefreshDriver()->MostRecentRefresh();
;
} else {
// reparent the element's style
nsStyleSet* styleSet = mPresContext->PresShell()->StyleSet();

View File

@ -20,10 +20,13 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.TabHost;
import android.widget.TabWidget;
public class AwesomeBarTabs extends TabHost {
public class AwesomeBarTabs extends TabHost
implements LightweightTheme.OnChangeListener {
private static final String LOGTAG = "GeckoAwesomeBarTabs";
private Context mContext;
private GeckoActivity mActivity;
private boolean mInflated;
private LayoutInflater mInflater;
private OnUrlOpenListener mUrlOpenListener;
@ -105,6 +108,8 @@ public class AwesomeBarTabs extends TabHost {
Log.d(LOGTAG, "Creating AwesomeBarTabs");
mContext = context;
mActivity = (GeckoActivity) context;
mInflated = false;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@ -174,20 +179,50 @@ public class AwesomeBarTabs extends TabHost {
filter("");
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
mActivity.getLightweightTheme().addListener(this);
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
mActivity.getLightweightTheme().removeListener(this);
}
@Override
public void onLightweightThemeChanged() {
styleSelectedTab();
}
@Override
public void onLightweightThemeReset() {
styleSelectedTab();
}
private void styleSelectedTab() {
int selIndex = mViewPager.getCurrentItem();
TabWidget tabWidget = getTabWidget();
boolean isPrivate = false;
if (mTarget != null && mTarget.equals(AwesomeBar.Target.CURRENT_TAB.name())) {
Tab tab = Tabs.getInstance().getSelectedTab();
if (tab != null)
isPrivate = tab.isPrivate();
}
for (int i = 0; i < tabWidget.getTabCount(); i++) {
GeckoTextView view = (GeckoTextView) tabWidget.getChildTabViewAt(i);
if (mTarget != null && mTarget.equals(AwesomeBar.Target.CURRENT_TAB.name())) {
Tab tab = Tabs.getInstance().getSelectedTab();
if (tab != null && tab.isPrivate()) {
if (i == selIndex)
view.setPrivateMode(false);
else
view.setPrivateMode(true);
}
if (isPrivate) {
view.setPrivateMode((i == selIndex) ? false : true);
} else {
if (i == selIndex)
view.resetTheme();
else if (mActivity.getLightweightTheme().isEnabled())
view.setTheme(mActivity.getLightweightTheme().isLightTheme());
else
view.resetTheme();
}
if (i == selIndex)
@ -328,7 +363,7 @@ public class AwesomeBarTabs extends TabHost {
drawable.setAlpha(255, 0);
StateListDrawable stateList = new StateListDrawable();
stateList.addState(new int[] { R.attr.state_private }, mActivity.getResources().getDrawable(R.drawable.address_bar_bg_private));
stateList.addState(new int[] { R.attr.state_private }, mActivity.getResources().getDrawable(R.drawable.abouthome_bg_pb_repeat));
stateList.addState(new int[] {}, drawable);
int[] padding = new int[] { getPaddingLeft(),

View File

@ -113,18 +113,20 @@ public class LightweightTheme implements GeckoEventListener {
}
public void resetLightweightTheme() {
// Reset the bitmap.
mBitmap = null;
if (mBitmap != null) {
// Reset the bitmap.
mBitmap = null;
// Post the reset on the UI thread.
for (OnChangeListener listener : mListeners) {
final OnChangeListener oneListener = listener;
oneListener.post(new Runnable() {
@Override
public void run() {
oneListener.onLightweightThemeReset();
}
});
// Post the reset on the UI thread.
for (OnChangeListener listener : mListeners) {
final OnChangeListener oneListener = listener;
oneListener.post(new Runnable() {
@Override
public void run() {
oneListener.onLightweightThemeReset();
}
});
}
}
}
@ -162,6 +164,21 @@ public class LightweightTheme implements GeckoEventListener {
}
}
/**
* A lightweight theme is enabled only if there is an active bitmap.
*
* @return True if the theme is enabled.
*/
public boolean isEnabled() {
return (mBitmap != null);
}
/**
* Based on the luminance of the domanint color, a theme is classified as light or dark.
*
* @return True if the theme is light.
*/
public boolean isLightTheme() {
return mIsLight;
}

View File

@ -410,6 +410,9 @@ public class TabsPanel extends TabHost
mVisible = false;
mPopupMenu.dismiss();
dispatchLayoutChange(0, 0);
mPanel.hide();
mPanel = null;
}
}

View File

@ -222,7 +222,7 @@ public class TabsTray extends ListView
}
private void removeTab(Tab tab) {
if (tab.isPrivate() == mIsPrivate) {
if (tab.isPrivate() == mIsPrivate && mTabs != null) {
mTabs.remove(tab);
notifyDataSetChanged(); // Be sure to call this whenever mTabs changes.
}

View File

@ -10,6 +10,12 @@
<!-- private browsing mode -->
<item gecko:state_private="true" android:color="#FFDDDDDD" />
<!-- dark theme -->
<item gecko:state_dark="true" android:color="#FFDDDDDD"/>
<!-- light theme -->
<item gecko:state_light="true" android:color="#FF222222"/>
<!-- normal mode -->
<item android:color="#FF222222"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -517,7 +517,7 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel)
#ifdef MOZ_ENABLE_D3D9_LAYER
case LAYERS_D3D9:
{
LayerManagerD3D9 *layerManagerD3D9 =
nsRefPtr<LayerManagerD3D9> layerManagerD3D9 =
static_cast<mozilla::layers::LayerManagerD3D9*>(GetLayerManager());
layerManagerD3D9->SetClippingRegion(region);
result = listener->PaintWindow(this, region, nsIWidgetListener::SENT_WILL_PAINT | nsIWidgetListener::WILL_SEND_DID_PAINT);
@ -577,6 +577,8 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel)
mPainting = false;
// Re-get the listener since painting may have killed it.
listener = GetPaintListener();
if (listener)
listener->DidPaintWindow();

View File

@ -239,32 +239,17 @@ struct nsCharTraits<PRUnichar>
}
/**
* Convert c to its lower-case form, but only if the lower-case form is
* ASCII. Otherwise leave it alone.
*
* There are only two non-ASCII Unicode characters whose lowercase
* equivalents are ASCII: KELVIN SIGN and LATIN CAPITAL LETTER I WITH
* DOT ABOVE. So it's a simple matter to handle those explicitly.
* Convert c to its lower-case form, but only if c is in the ASCII
* range. Otherwise leave it alone.
*/
static
char_type
ASCIIToLower( char_type c )
{
if (c < 0x100)
{
if (c >= 'A' && c <= 'Z')
return char_type(c + ('a' - 'A'));
if (c >= 'A' && c <= 'Z')
return char_type(c + ('a' - 'A'));
return c;
}
else
{
if (c == 0x212A) // KELVIN SIGN
return 'k';
if (c == 0x0130) // LATIN CAPITAL LETTER I WITH DOT ABOVE
return 'i';
return c;
}
return c;
}
static

View File

@ -299,11 +299,12 @@ class nsTSubstring_CharT
}
#endif
// The LowerCaseEquals methods compare the lower case version of
// this string to some ASCII/Literal string. The ASCII string is
// *not* lowercased for you. If you compare to an ASCII or literal
// string that contains an uppercase character, it is guaranteed to
// return false. We will throw assertions too.
// The LowerCaseEquals methods compare the ASCII-lowercase version of
// this string (lowercasing only ASCII uppercase characters) to some
// ASCII/Literal string. The ASCII string is *not* lowercased for
// you. If you compare to an ASCII or literal string that contains an
// uppercase character, it is guaranteed to return false. We will
// throw assertions too.
bool NS_FASTCALL LowerCaseEqualsASCII( const char* data, size_type len ) const;
bool NS_FASTCALL LowerCaseEqualsASCII( const char* data ) const;