Merge mozilla-central to autoland. a=merge CLOSED TREE

This commit is contained in:
Bogdan Tara 2019-04-05 19:21:43 +03:00
Родитель e204fc0102 621ec01c2c
Коммит 7a0e800fa9
17 изменённых файлов: 337 добавлений и 67 удалений

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

@ -1653,6 +1653,17 @@ nsDOMWindowUtils::GetFocusedInputType(nsAString& aType) {
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetFocusedActionHint(nsAString& aType) {
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
aType = widget->GetInputContext().mActionHint;
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetViewId(Element* aElement, nsViewID* aResult) {
if (aElement && nsLayoutUtils::FindIDFor(aElement, aResult)) {

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

@ -150,6 +150,23 @@ class nsFocusManager final : public nsIFocusManager,
nsPIDOMWindowOuter* aWindow, SearchRange aSearchRange,
nsPIDOMWindowOuter** aFocusedWindow);
/**
* Helper function for MoveFocus which determines the next element
* to move the focus to and returns it in aNextContent.
*
* aWindow is the window to adjust the focus within, and aStart is
* the element to start navigation from. For tab key navigation,
* this should be the currently focused element.
*
* aType is the type passed to MoveFocus. If aNoParentTraversal is set,
* navigation is not done to parent documents and iteration returns to the
* beginning (or end) of the starting document.
*/
nsresult DetermineElementToMoveFocus(nsPIDOMWindowOuter* aWindow,
nsIContent* aStart, int32_t aType,
bool aNoParentTraversal,
nsIContent** aNextContent);
/**
* Returns the content node that focus will be redirected to if aContent was
* focused. This is used for the special case of certain XUL elements such
@ -403,23 +420,6 @@ class nsFocusManager final : public nsIFocusManager,
nsIContent** aStartContent,
nsIContent** aEndContent);
/**
* Helper function for MoveFocus which determines the next element
* to move the focus to and returns it in aNextContent.
*
* aWindow is the window to adjust the focus within, and aStart is
* the element to start navigation from. For tab key navigation,
* this should be the currently focused element.
*
* aType is the type passed to MoveFocus. If aNoParentTraversal is set,
* navigation is not done to parent documents and iteration returns to the
* beginning (or end) of the starting document.
*/
nsresult DetermineElementToMoveFocus(nsPIDOMWindowOuter* aWindow,
nsIContent* aStart, int32_t aType,
bool aNoParentTraversal,
nsIContent** aNextContent);
/**
* Retrieve the next tabbable element in scope owned by aOwner, using
* focusability and tabindex to determine the tab order.

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

@ -20,6 +20,7 @@
#include "mozilla/Unused.h"
#include "mozilla/dom/BrowserBridgeChild.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "mozilla/dom/HTMLTextAreaElement.h"
#include "mozilla/dom/MouseEventBinding.h"
#include "mozilla/dom/TabParent.h"
@ -28,6 +29,7 @@
#include "nsCOMPtr.h"
#include "nsContentUtils.h"
#include "nsFocusManager.h"
#include "nsIContent.h"
#include "mozilla/dom/Document.h"
#include "nsIForm.h"
@ -1179,6 +1181,123 @@ void IMEStateManager::SetInputContextForChildProcess(
SetInputContext(widget, aInputContext, aAction);
}
static bool IsNextFocusableElementTextOrNumberControl(Element* aInputContent) {
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (!fm) {
return false;
}
nsCOMPtr<nsIContent> nextContent;
nsresult rv = fm->DetermineElementToMoveFocus(
aInputContent->OwnerDoc()->GetWindow(), aInputContent,
nsIFocusManager::MOVEFOCUS_FORWARD, true, getter_AddRefs(nextContent));
if (NS_WARN_IF(NS_FAILED(rv)) || !nextContent) {
return false;
}
nextContent = nextContent->FindFirstNonChromeOnlyAccessContent();
nsCOMPtr<nsIFormControl> nextControl = do_QueryInterface(nextContent);
if (!nextControl || !nextControl->IsTextOrNumberControl(false)) {
return false;
}
// XXX We don't consider next element is date/time control yet.
nsGenericHTMLElement* nextElement =
nsGenericHTMLElement::FromNodeOrNull(nextContent);
if (!nextElement) {
return false;
}
bool focusable = false;
nextElement->IsHTMLFocusable(false, &focusable, nullptr);
if (!focusable) {
return false;
}
// Check readonly attribute.
if (nextElement->IsHTMLElement(nsGkAtoms::textarea)) {
HTMLTextAreaElement* textAreaElement =
HTMLTextAreaElement::FromNodeOrNull(nextElement);
return !textAreaElement->ReadOnly();
}
// If neither textarea nor input, what element type?
MOZ_DIAGNOSTIC_ASSERT(nextElement->IsHTMLElement(nsGkAtoms::input));
HTMLInputElement* inputElement =
HTMLInputElement::FromNodeOrNull(nextElement);
return !inputElement->ReadOnly();
}
static void GetActionHint(nsIContent& aContent, nsAString& aActionHint) {
aContent.AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
aActionHint);
if (!aActionHint.IsEmpty()) {
return;
}
// Get the input content corresponding to the focused node,
// which may be an anonymous child of the input content.
nsIContent* inputContent = aContent.FindFirstNonChromeOnlyAccessContent();
if (!inputContent->IsHTMLElement(nsGkAtoms::input)) {
return;
}
// If we don't have an action hint and
// return won't submit the form, use "next".
bool willSubmit = false;
bool isLastElement = false;
nsCOMPtr<nsIFormControl> control(do_QueryInterface(inputContent));
Element* formElement = nullptr;
if (control) {
formElement = control->GetFormElement();
// is this a form and does it have a default submit element?
if (formElement) {
HTMLFormElement* htmlForm = nullptr;
if (formElement->IsHTMLElement(nsGkAtoms::form)) {
htmlForm = HTMLFormElement::FromNodeOrNull(formElement);
if (htmlForm->IsLastActiveElement(control)) {
isLastElement = true;
}
}
nsCOMPtr<nsIForm> form = do_QueryInterface(formElement);
if (form && form->GetDefaultSubmitElement()) {
willSubmit = true;
// is this an html form...
} else if (htmlForm) {
// ... and does it only have a single text input element ?
if (!htmlForm->ImplicitSubmissionIsDisabled() ||
// ... or is this the last non-disabled element?
isLastElement) {
willSubmit = true;
}
}
}
if (!isLastElement && formElement) {
// If next tabbable content in form is text control, hint should be "next"
// even there is submit in form.
if (IsNextFocusableElementTextOrNumberControl(
inputContent->AsElement())) {
// This is focusable text control
// XXX What good hint for read only field?
aActionHint.AssignLiteral("next");
return;
}
}
}
if (!willSubmit) {
return;
}
if (control->ControlType() == NS_FORM_INPUT_SEARCH) {
aActionHint.AssignLiteral("search");
return;
}
aActionHint.AssignLiteral("go");
}
// static
void IMEStateManager::SetIMEState(const IMEState& aState,
nsPresContext* aPresContext,
@ -1245,46 +1364,7 @@ void IMEStateManager::SetIMEState(const IMEState& aState,
}
}
aContent->AsElement()->GetAttr(
kNameSpaceID_None, nsGkAtoms::moz_action_hint, context.mActionHint);
// Get the input content corresponding to the focused node,
// which may be an anonymous child of the input content.
nsIContent* inputContent = aContent->FindFirstNonChromeOnlyAccessContent();
// If we don't have an action hint and
// return won't submit the form, use "next".
if (context.mActionHint.IsEmpty() &&
inputContent->IsHTMLElement(nsGkAtoms::input)) {
bool willSubmit = false;
nsCOMPtr<nsIFormControl> control(do_QueryInterface(inputContent));
mozilla::dom::Element* formElement = nullptr;
nsCOMPtr<nsIForm> form;
if (control) {
formElement = control->GetFormElement();
// is this a form and does it have a default submit element?
if ((form = do_QueryInterface(formElement)) &&
form->GetDefaultSubmitElement()) {
willSubmit = true;
// is this an html form...
} else if (formElement && formElement->IsHTMLElement(nsGkAtoms::form)) {
dom::HTMLFormElement* htmlForm =
static_cast<dom::HTMLFormElement*>(formElement);
// ... and does it only have a single text input element ?
if (!htmlForm->ImplicitSubmissionIsDisabled() ||
// ... or is this the last non-disabled element?
htmlForm->IsLastActiveElement(control)) {
willSubmit = true;
}
}
}
context.mActionHint.Assign(
willSubmit
? (control->ControlType() == NS_FORM_INPUT_SEARCH
? NS_LITERAL_STRING("search")
: NS_LITERAL_STRING("go"))
: (formElement ? NS_LITERAL_STRING("next") : EmptyString()));
}
GetActionHint(*aContent, context.mActionHint);
}
// XXX I think that we should use nsContentUtils::IsCallerChrome() instead

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

@ -1621,7 +1621,8 @@ bool HTMLFormElement::IsLastActiveElement(
MOZ_ASSERT(aControl, "Unexpected call");
for (auto* element : Reversed(mControls->mElements)) {
if (element->IsSingleLineTextOrNumberControl(false) &&
// XXX How about date/time control?
if (element->IsTextOrNumberControl(false) &&
!element->IsDisabled()) {
return element == aControl;
}

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

@ -1466,6 +1466,11 @@ interface nsIDOMWindowUtils : nsISupports {
*/
readonly attribute AString focusedInputType;
/**
* Get the action hint of the currently focused html input, if any.
*/
readonly attribute AString focusedActionHint;
/**
* Find the view ID for a given element. This is the reverse of
* findElementWithViewId().

Двоичные данные
dom/localstorage/test/unit/stringLength2_profile.zip Normal file

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

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

@ -0,0 +1,76 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/**
* This test is mainly to verify that string length is correctly computed for
* database values containing NULs. See bug 1541681.
*/
async function testSteps() {
const principal = getPrincipal("http://example.org");
const data = {};
data.key = "foobar";
data.secondKey = "foobaz";
data.value = {
length: 19253,
};
data.usage = data.key.length + data.value.length;
async function checkUsage(expectedUsage) {
info("Checking usage");
// This forces any pending changes to be flushed to disk. It also forces
// data to be reloaded from disk at next localStorage API call.
request = resetOrigin(principal);
await requestFinished(request);
request = getOriginUsage(principal);
await requestFinished(request);
is(request.result.usage, expectedUsage, "Correct usage");
}
info("Setting pref");
Services.prefs.setBoolPref("dom.storage.next_gen", true);
info("Stage 1 - Checking usage after profile installation");
info("Clearing");
let request = clear();
await requestFinished(request);
info("Installing package");
// The profile contains storage.sqlite and webappsstore.sqlite.
installPackage("stringLength2_profile");
await checkUsage(0);
info("Stage 2 - Checking usage after archived data migration");
info("Opening database");
let storage = getLocalStorage(principal);
storage.open();
await checkUsage(data.usage);
info("Stage 3 - Checking usage after copying the value");
info("Adding a second copy of the value");
let value = storage.getItem(data.key);
storage.setItem(data.secondKey, value);
await checkUsage(2 * data.usage);
info("Stage 4 - Checking length of the copied value");
value = storage.getItem(data.secondKey);
ok(value.length === data.value.length, "Correct string length");
}

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

@ -9,6 +9,7 @@ support-files =
corruptedDatabase_profile.zip
groupMismatch_profile.zip
migration_profile.zip
stringLength2_profile.zip
stringLength_profile.zip
[test_archive.js]
@ -36,4 +37,5 @@ run-sequentially = this test depends on a file produced by test_databaseShadowin
[test_originInit.js]
[test_snapshotting.js]
[test_stringLength.js]
[test_stringLength2.js]
[test_usage.js]

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

@ -602,7 +602,7 @@ import java.lang.reflect.Proxy;
case KeyEvent.KEYCODE_ENTER:
if ((event.getFlags() & KeyEvent.FLAG_EDITOR_ACTION) != 0 &&
mIMEActionHint.equalsIgnoreCase("next")) {
return new KeyEvent(event.getAction(), KeyEvent.KEYCODE_TAB);
return new KeyEvent(event.getDownTime(), event.getEventTime(), event.getAction(), KeyEvent.KEYCODE_TAB, 0);
}
break;
}

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

@ -1,8 +1,29 @@
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
if (AppConstants.platform != "android") {
// We load HTML documents, which try to track link state, which requires
// the history service, which requires a profile.
do_get_profile();
}
function run_test() {
// vectors by the html5security project (https://code.google.com/p/html5security/ & Creative Commons 3.0 BY), see CC-BY-LICENSE for the full license
load("results.js"); // gives us a `vectors' array
/* import-globals-from ./results.js */
if (AppConstants.platform != "android") {
// xpcshell tests are weird. They fake shutdown after the test finishes. This upsets this test
// because it will try to create the history service to check for visited state on the links
// we're parsing.
// Creating the history service midway through shutdown breaks.
// We can't catch this in the history component because we're not *actually* shutting down,
// and so the app startup's service's `shuttingDown` bool is false, even though normally that
// is set to true *before* profile-change-teardown notifications are fired.
// To work around this, just force the history service to be created earlier:
let {PlacesUtils} = ChromeUtils.import("resource://gre/modules/PlacesUtils.jsm");
Assert.ok(PlacesUtils.history.databaseStatus <= 1, "ensure places database is successfully initialized.");
}
var ParserUtils = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils);
var sanitizeFlags = ParserUtils.SanitizerCidEmbedsOnly | ParserUtils.SanitizerDropForms | ParserUtils.SanitizerDropNonCSSPresentation;
// flags according to

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

@ -347,10 +347,7 @@ void utf16LengthFunction(sqlite3_context *aCtx, int aArgc,
sqlite3_value **aArgv) {
NS_ASSERTION(1 == aArgc, "Invalid number of arguments!");
nsDependentString data(
static_cast<const char16_t *>(::sqlite3_value_text16(aArgv[0])));
int len = data.Length();
int len = ::sqlite3_value_bytes16(aArgv[0]) / sizeof(char16_t);
// Set the result.
::sqlite3_result_int(aCtx, len);

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

@ -102,7 +102,8 @@ nsIWidget* nsWebBrowser::EnsureWidget() {
already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget,
const OriginAttributes& aOriginAttributes,
dom::BrowsingContext* aBrowsingContext) {
dom::BrowsingContext* aBrowsingContext,
bool aDisableHistory /* = false */) {
RefPtr<nsWebBrowser> browser = new nsWebBrowser(
aBrowsingContext->IsContent() ? typeContentWrapper : typeChromeWrapper);
@ -152,7 +153,7 @@ already_AddRefed<nsWebBrowser> nsWebBrowser::Create(
docShell->InitSessionHistory();
if (XRE_IsParentProcess()) {
if (XRE_IsParentProcess() && !aDisableHistory) {
// Hook up global history. Do not fail if we can't - just warn.
DebugOnly<nsresult> rv =
browser->EnableGlobalHistory(browser->mShouldEnableHistory);

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

@ -108,7 +108,8 @@ class nsWebBrowser final : public nsIWebBrowser,
static already_AddRefed<nsWebBrowser> Create(
nsIWebBrowserChrome* aContainerWindow, nsIWidget* aParentWidget,
const mozilla::OriginAttributes& aOriginAttributes,
mozilla::dom::BrowsingContext* aBrowsingContext);
mozilla::dom::BrowsingContext* aBrowsingContext,
bool aDisableHistory = false);
protected:
virtual ~nsWebBrowser();

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

@ -1445,6 +1445,16 @@ History::History()
mObservers(VISIT_OBSERVERS_INITIAL_CACHE_LENGTH),
mRecentlyVisitedURIs(RECENTLY_VISITED_URIS_SIZE) {
NS_ASSERTION(!gService, "Ruh-roh! This service has already been created!");
if (XRE_IsParentProcess()) {
nsCOMPtr<nsIProperties> dirsvc = services::GetDirectoryService();
bool haveProfile = false;
MOZ_RELEASE_ASSERT(
dirsvc &&
NS_SUCCEEDED(
dirsvc->Has(NS_APP_USER_PROFILE_50_DIR, &haveProfile)) &&
haveProfile,
"Can't construct history service if there is no profile.");
}
gService = this;
nsCOMPtr<nsIObserverService> os = services::GetObserverService();

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

@ -3,6 +3,7 @@ support-files = utils.js
[test_AltGr_key_events_in_web_content_on_windows.html]
skip-if = toolkit != 'windows' || headless # headless: Bug 1410525
[test_actionhint.html]
[test_assign_event_data.html]
subsuite = clipboard
skip-if = toolkit == "cocoa" || (toolkit == 'android' && debug) || android_version == '24' # Mac: Bug 933303, Android bug 1285414

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

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html>
<head>
<title>Tests for action hint that is used by software keyboard</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SpecialPowers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<div>
<form><input type="text" id="a1"><input type="text" id="a2"><input type="submit"></form>
<form><input type="search" id="b1"><input type="submit"></form>
<form><input type="text" id="c1"></form>
<form><input type="text" id="d1"><textarea></textarea><input type="submit"></form>
<form><input type="text" id="e1"><input type="number"><input type="submit"></form>
<form><input type="text" id="f1"><input type="date"><input type="submit"></form>
<form><input type="text" id="g1"><input type="radio"><input type="submit"></form>
<form><input type="text" id="h1"><input type="text" readonly><input type="submit"></form>
<form><input type="text" id="i1"><input type="text" disabled><input type="submit"></form>
<input type="text" id="j1"><input type="text"><input type="button">
<form><input type="text" id="k1"><a href="#foo">foo</a><input type="text"><input type="submit"></form>
</div>
<pre id="test">
<script class=testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(() => {
const tests = [
{ id: "a1", hint: "next", desc: "next element is type=text" },
{ id: "a2", hint: "go", desc: "next element is type=submit" },
{ id: "b1", hint: "search", desc: "current is type=search" },
{ id: "c1", hint: "go", desc: "only this element" },
{ id: "d1", hint: "next", desc: "next element is textarea" },
{ id: "e1", hint: "next", desc: "next element is type=number" },
{ id: "h1", hint: "go", desc: "next element is readonly" },
// XXX Feel free to change this result if you get some bugs reports
{ id: "i1", hint: "go", desc: "next element is disabled" },
{ id: "j1", hint: "", desc: "no form element" },
];
const todo_tests = [
{ id: "f1", hint: "next", desc: "next element is type=date" },
{ id: "k1", hint: "", desc: "next is anchor link" },
];
for (let test of tests) {
document.getElementById(test.id).focus();
is(SpecialPowers.DOMWindowUtils.focusedActionHint, test.hint, test.desc);
}
for (let test of todo_tests) {
document.getElementById(test.id).focus();
todo_is(SpecialPowers.DOMWindowUtils.focusedActionHint, test.hint, test.desc);
}
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

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

@ -495,7 +495,8 @@ nsAppShellService::CreateWindowlessBrowser(bool aIsChrome,
* an associated doc shell, which is what we're interested in.
*/
nsCOMPtr<nsIWebBrowser> browser =
nsWebBrowser::Create(stub, widget, OriginAttributes(), browsingContext);
nsWebBrowser::Create(stub, widget, OriginAttributes(), browsingContext,
true /* disable history */);
if (NS_WARN_IF(!browser)) {
NS_ERROR("Couldn't create instance of nsWebBrowser!");