зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
d401f28d4e
Двоичный файл не отображается.
|
@ -8,24 +8,23 @@
|
|||
.notificationbox .notificationInner {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.notificationbox .details {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.notificationbox .notification-button {
|
||||
text-align: right;
|
||||
.notificationInner .messageText {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.notificationbox .messageText {
|
||||
flex-grow: 1;
|
||||
.notificationInner .messageImage,
|
||||
.notificationbox .notificationButton,
|
||||
.notificationbox .messageCloseButton {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.notificationbox .details:dir(rtl)
|
||||
.notificationbox .notificationInner:dir(rtl) {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
@ -50,7 +49,6 @@
|
|||
}
|
||||
|
||||
.notificationbox .messageImage {
|
||||
display: inline-block;
|
||||
background-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
|
|
@ -202,7 +202,7 @@ class NotificationBox extends Component {
|
|||
return (
|
||||
button({
|
||||
key: props.label,
|
||||
className: "notification-button",
|
||||
className: "notificationButton",
|
||||
accesskey: props.accesskey,
|
||||
onClick: onClick},
|
||||
props.label
|
||||
|
@ -220,17 +220,20 @@ class NotificationBox extends Component {
|
|||
className: "notification",
|
||||
"data-key": notification.value,
|
||||
"data-type": notification.type},
|
||||
div({className: "notificationInner"},
|
||||
div({className: "details"},
|
||||
div({
|
||||
className: "messageImage",
|
||||
"data-type": notification.type}),
|
||||
span({className: "messageText"},
|
||||
notification.label
|
||||
),
|
||||
notification.buttons.map(props =>
|
||||
this.renderButton(props, notification)
|
||||
)
|
||||
div(
|
||||
{className: "notificationInner"},
|
||||
div({
|
||||
className: "messageImage",
|
||||
"data-type": notification.type,
|
||||
}),
|
||||
span({
|
||||
className: "messageText",
|
||||
title: notification.label,
|
||||
},
|
||||
notification.label
|
||||
),
|
||||
notification.buttons.map(props =>
|
||||
this.renderButton(props, notification)
|
||||
),
|
||||
div({
|
||||
className: "messageCloseButton",
|
||||
|
|
|
@ -54,7 +54,7 @@ window.onload = async function () {
|
|||
);
|
||||
|
||||
let buttonNodes = notificationNode.querySelectorAll(
|
||||
".notification-button");
|
||||
".notificationButton");
|
||||
|
||||
is(buttonNodes.length, 2, "There must be two buttons");
|
||||
|
||||
|
|
|
@ -654,6 +654,14 @@ a.learn-more-link.webconsole-learn-more-link {
|
|||
color: currentColor;
|
||||
}
|
||||
|
||||
/* Special casing warning and error string colors so they are legible */
|
||||
.theme-dark .message.error .objectBox-string,
|
||||
.theme-light .message.error .objectBox-string,
|
||||
.theme-dark .message.warn .objectBox-string,
|
||||
.theme-light .message.warn .objectBox-string {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
/* Special casing dark-theme error and warning ObjectInspector colors */
|
||||
.theme-dark .webconsole-output-wrapper .message.error .tree.object-inspector .object-label,
|
||||
.theme-dark .webconsole-output-wrapper .message.error .tree.object-inspector .object-label *,
|
||||
|
|
|
@ -141,6 +141,7 @@ add_task(async function() {
|
|||
add_task(async function() {
|
||||
info("Test UA widgets when showUserAgentShadowRoots is true");
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.ua_widget.enabled", true],
|
||||
["devtools.inspector.showUserAgentShadowRoots", true],
|
||||
]});
|
||||
|
||||
|
@ -160,6 +161,7 @@ add_task(async function() {
|
|||
add_task(async function() {
|
||||
info("Test UA widgets when showUserAgentShadowRoots is false");
|
||||
await SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.ua_widget.enabled", true],
|
||||
["devtools.inspector.showUserAgentShadowRoots", false],
|
||||
]});
|
||||
|
||||
|
|
|
@ -45,3 +45,6 @@ DEPRECATED_OPERATION(DOMAttrModifiedEvent)
|
|||
DEPRECATED_OPERATION(MozBoxOrInlineBoxDisplay)
|
||||
DEPRECATED_OPERATION(DOMQuadBoundsAttr)
|
||||
DEPRECATED_OPERATION(CreateImageBitmapCanvasRenderingContext2D)
|
||||
DEPRECATED_OPERATION(MozRequestFullScreenDeprecatedPrefix)
|
||||
DEPRECATED_OPERATION(MozfullscreenchangeDeprecatedPrefix)
|
||||
DEPRECATED_OPERATION(MozfullscreenerrorDeprecatedPrefix)
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "EmptyBody.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(EmptyBody)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(EmptyBody)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(EmptyBody)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EmptyBody)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAbortSignalImpl)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchStreamReader)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(EmptyBody)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAbortSignalImpl)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchStreamReader)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(EmptyBody)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EmptyBody)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
EmptyBody::EmptyBody(nsIGlobalObject* aGlobal,
|
||||
mozilla::ipc::PrincipalInfo* aPrincipalInfo,
|
||||
AbortSignalImpl* aAbortSignalImpl,
|
||||
already_AddRefed<nsIInputStream> aBodyStream)
|
||||
: FetchBody<EmptyBody>(aGlobal)
|
||||
, mPrincipalInfo(aPrincipalInfo)
|
||||
, mAbortSignalImpl(aAbortSignalImpl)
|
||||
, mBodyStream(std::move(aBodyStream))
|
||||
{}
|
||||
|
||||
EmptyBody::~EmptyBody() = default;
|
||||
|
||||
/* static */ already_AddRefed<EmptyBody>
|
||||
EmptyBody::Create(nsIGlobalObject* aGlobal,
|
||||
mozilla::ipc::PrincipalInfo* aPrincipalInfo,
|
||||
AbortSignalImpl* aAbortSignalImpl,
|
||||
const nsACString& aMimeType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIInputStream> bodyStream;
|
||||
aRv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), EmptyCString());
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<EmptyBody> emptyBody = new EmptyBody(aGlobal, aPrincipalInfo,
|
||||
aAbortSignalImpl,
|
||||
bodyStream.forget());
|
||||
emptyBody->OverrideMimeType(aMimeType);
|
||||
return emptyBody.forget();
|
||||
}
|
||||
|
||||
void
|
||||
EmptyBody::GetBody(nsIInputStream** aStream, int64_t* aBodyLength)
|
||||
{
|
||||
MOZ_ASSERT(aStream);
|
||||
|
||||
if (aBodyLength) {
|
||||
*aBodyLength = 0;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> bodyStream = mBodyStream;
|
||||
bodyStream.forget(aStream);
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
|
@ -0,0 +1,89 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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_EmptyBody_h
|
||||
#define mozilla_dom_EmptyBody_h
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
#include "mozilla/dom/Fetch.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class PrincipalInfo;
|
||||
} // namespace ipc
|
||||
|
||||
namespace dom {
|
||||
|
||||
class EmptyBody final : public nsISupports
|
||||
, public FetchBody<EmptyBody>
|
||||
{
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(EmptyBody)
|
||||
|
||||
public:
|
||||
static already_AddRefed<EmptyBody>
|
||||
Create(nsIGlobalObject* aGlobal,
|
||||
mozilla::ipc::PrincipalInfo* aPrincipalInfo,
|
||||
AbortSignalImpl* aAbortSignalImpl,
|
||||
const nsACString& aMimeType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsIGlobalObject*
|
||||
GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
AbortSignalImpl*
|
||||
GetSignalImpl() const override
|
||||
{
|
||||
return mAbortSignalImpl;
|
||||
}
|
||||
|
||||
const UniquePtr<mozilla::ipc::PrincipalInfo>&
|
||||
GetPrincipalInfo() const
|
||||
{
|
||||
return mPrincipalInfo;
|
||||
}
|
||||
|
||||
void
|
||||
GetBody(nsIInputStream** aStream, int64_t* aBodyLength = nullptr);
|
||||
|
||||
using FetchBody::BodyBlobURISpec;
|
||||
|
||||
const nsACString&
|
||||
BodyBlobURISpec() const
|
||||
{
|
||||
return EmptyCString();
|
||||
}
|
||||
|
||||
using FetchBody::BodyLocalPath;
|
||||
|
||||
const nsAString&
|
||||
BodyLocalPath() const
|
||||
{
|
||||
return EmptyString();
|
||||
}
|
||||
|
||||
private:
|
||||
EmptyBody(nsIGlobalObject* aGlobal,
|
||||
mozilla::ipc::PrincipalInfo* aPrincipalInfo,
|
||||
AbortSignalImpl* aAbortSignalImpl,
|
||||
already_AddRefed<nsIInputStream> mBodyStream);
|
||||
|
||||
~EmptyBody();
|
||||
|
||||
UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
|
||||
RefPtr<AbortSignalImpl> mAbortSignalImpl;
|
||||
nsCOMPtr<nsIInputStream> mBodyStream;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_EmptyBody_h
|
|
@ -40,6 +40,7 @@
|
|||
#include "mozilla/Telemetry.h"
|
||||
|
||||
#include "BodyExtractor.h"
|
||||
#include "EmptyBody.h"
|
||||
#include "FetchObserver.h"
|
||||
#include "InternalRequest.h"
|
||||
#include "InternalResponse.h"
|
||||
|
@ -1242,6 +1243,29 @@ FetchBody<Derived>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Null bodies are a special-case in the fetch spec. The Body mix-in can only
|
||||
// be "disturbed" or "locked" if its associated "body" is non-null.
|
||||
// Additionally, the Body min-in's "consume body" algorithm explicitly creates
|
||||
// a fresh empty ReadableStream object in step 2. This means that `bodyUsed`
|
||||
// will never return true for a null body.
|
||||
//
|
||||
// To this end, we create a fresh (empty) body every time a request is made
|
||||
// and consume its body here, without marking this FetchBody consumed via
|
||||
// SetBodyUsed.
|
||||
nsCOMPtr<nsIInputStream> bodyStream;
|
||||
DerivedClass()->GetBody(getter_AddRefs(bodyStream));
|
||||
if (!bodyStream) {
|
||||
RefPtr<EmptyBody> emptyBody =
|
||||
EmptyBody::Create(DerivedClass()->GetParentObject(),
|
||||
DerivedClass()->GetPrincipalInfo().get(),
|
||||
signalImpl, mMimeType, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return emptyBody->ConsumeBody(aCx, aType, aRv);
|
||||
}
|
||||
|
||||
SetBodyUsed(aCx, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
|
@ -1251,7 +1275,7 @@ FetchBody<Derived>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
|
|||
|
||||
RefPtr<Promise> promise =
|
||||
FetchBodyConsumer<Derived>::Create(global, mMainThreadEventTarget, this,
|
||||
signalImpl, aType, aRv);
|
||||
bodyStream, signalImpl, aType, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1269,6 +1293,11 @@ already_AddRefed<Promise>
|
|||
FetchBody<Response>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
template
|
||||
already_AddRefed<Promise>
|
||||
FetchBody<EmptyBody>::ConsumeBody(JSContext* aCx, FetchConsumeType aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
FetchBody<Derived>::SetMimeType()
|
||||
|
@ -1297,6 +1326,13 @@ template
|
|||
void
|
||||
FetchBody<Response>::SetMimeType();
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
FetchBody<Derived>::OverrideMimeType(const nsACString& aMimeType)
|
||||
{
|
||||
mMimeType = aMimeType;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
const nsACString&
|
||||
FetchBody<Derived>::BodyBlobURISpec() const
|
||||
|
@ -1312,6 +1348,10 @@ template
|
|||
const nsACString&
|
||||
FetchBody<Response>::BodyBlobURISpec() const;
|
||||
|
||||
template
|
||||
const nsACString&
|
||||
FetchBody<EmptyBody>::BodyBlobURISpec() const;
|
||||
|
||||
template <class Derived>
|
||||
const nsAString&
|
||||
FetchBody<Derived>::BodyLocalPath() const
|
||||
|
@ -1327,6 +1367,10 @@ template
|
|||
const nsAString&
|
||||
FetchBody<Response>::BodyLocalPath() const;
|
||||
|
||||
template
|
||||
const nsAString&
|
||||
FetchBody<EmptyBody>::BodyLocalPath() const;
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
FetchBody<Derived>::SetReadableStreamBody(JSContext* aCx, JSObject* aBody)
|
||||
|
|
|
@ -267,6 +267,9 @@ public:
|
|||
void
|
||||
Abort() override;
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ConsumeBody(JSContext* aCx, FetchConsumeType aType, ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIGlobalObject> mOwner;
|
||||
|
||||
|
@ -288,6 +291,9 @@ protected:
|
|||
void
|
||||
SetMimeType();
|
||||
|
||||
void
|
||||
OverrideMimeType(const nsACString& aMimeType);
|
||||
|
||||
void
|
||||
SetReadableStreamBody(JSContext* aCx, JSObject* aBody);
|
||||
|
||||
|
@ -298,9 +304,6 @@ private:
|
|||
return static_cast<Derived*>(const_cast<FetchBody*>(this));
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
ConsumeBody(JSContext* aCx, FetchConsumeType aType, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
LockStream(JSContext* aCx, JS::HandleObject aStream, ErrorResult& aRv);
|
||||
|
||||
|
|
|
@ -323,22 +323,15 @@ template <class Derived>
|
|||
FetchBodyConsumer<Derived>::Create(nsIGlobalObject* aGlobal,
|
||||
nsIEventTarget* aMainThreadEventTarget,
|
||||
FetchBody<Derived>* aBody,
|
||||
nsIInputStream* aBodyStream,
|
||||
AbortSignalImpl* aSignalImpl,
|
||||
FetchConsumeType aType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(aBody);
|
||||
MOZ_ASSERT(aBodyStream);
|
||||
MOZ_ASSERT(aMainThreadEventTarget);
|
||||
|
||||
nsCOMPtr<nsIInputStream> bodyStream;
|
||||
aBody->DerivedClass()->GetBody(getter_AddRefs(bodyStream));
|
||||
if (!bodyStream) {
|
||||
aRv = NS_NewCStringInputStream(getter_AddRefs(bodyStream), EmptyCString());
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(aGlobal, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
|
@ -346,7 +339,7 @@ FetchBodyConsumer<Derived>::Create(nsIGlobalObject* aGlobal,
|
|||
|
||||
RefPtr<FetchBodyConsumer<Derived>> consumer =
|
||||
new FetchBodyConsumer<Derived>(aMainThreadEventTarget, aGlobal,
|
||||
aBody, bodyStream, promise,
|
||||
aBody, aBodyStream, promise,
|
||||
aType);
|
||||
|
||||
RefPtr<ThreadSafeWorkerRef> workerRef;
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
Create(nsIGlobalObject* aGlobal,
|
||||
nsIEventTarget* aMainThreadEventTarget,
|
||||
FetchBody<Derived>* aBody,
|
||||
nsIInputStream* aBodyStream,
|
||||
AbortSignalImpl* aSignalImpl,
|
||||
FetchConsumeType aType,
|
||||
ErrorResult& aRv);
|
||||
|
|
|
@ -27,6 +27,7 @@ EXPORTS.mozilla.dom += [
|
|||
UNIFIED_SOURCES += [
|
||||
'BodyExtractor.cpp',
|
||||
'ChannelInfo.cpp',
|
||||
'EmptyBody.cpp',
|
||||
'Fetch.cpp',
|
||||
'FetchConsumer.cpp',
|
||||
'FetchDriver.cpp',
|
||||
|
|
|
@ -355,3 +355,9 @@ DOMQuadBoundsAttrWarning=DOMQuad.bounds is deprecated in favor of DOMQuad.getBou
|
|||
UnsupportedEntryTypesIgnored=Ignoring unsupported entryTypes: %S.
|
||||
# LOCALIZATION NOTE (CreateImageBitmapCanvasRenderingContext2DWarning): Do not translate CanvasRenderingContext2D and createImageBitmap.
|
||||
CreateImageBitmapCanvasRenderingContext2DWarning=Use of CanvasRenderingContext2D in createImageBitmap is deprecated.
|
||||
# LOCALIZATION NOTE (MozRequestFullScreenDeprecatedPrefixWarning): Do not translate mozRequestFullScreen.
|
||||
MozRequestFullScreenDeprecatedPrefixWarning=mozRequestFullScreen() is deprecated.
|
||||
# LOCALIZATION NOTE (MozfullscreenchangeDeprecatedPrefixWarning): Do not translate onmozfullscreenchange.
|
||||
MozfullscreenchangeDeprecatedPrefixWarning=onmozfullscreenchange is deprecated.
|
||||
# LOCALIZATION NOTE (MozfullscreenerrorDeprecatedPrefixWarning): Do not translate onmozfullscreenerror.
|
||||
MozfullscreenerrorDeprecatedPrefixWarning=onmozfullscreenerror is deprecated.
|
||||
|
|
|
@ -263,7 +263,7 @@ Element implements GeometryUtils;
|
|||
partial interface Element {
|
||||
[Throws, Func="nsDocument::IsUnprefixedFullscreenEnabled", NeedsCallerType]
|
||||
Promise<void> requestFullscreen();
|
||||
[Throws, BinaryName="requestFullscreen", NeedsCallerType]
|
||||
[Throws, BinaryName="requestFullscreen", NeedsCallerType, Deprecated="MozRequestFullScreenDeprecatedPrefix"]
|
||||
Promise<void> mozRequestFullScreen();
|
||||
|
||||
// Events handlers
|
||||
|
|
|
@ -118,7 +118,9 @@ interface GlobalEventHandlers {
|
|||
|
||||
// Mozilla-specific handlers. Unprefixed handlers live in
|
||||
// Document rather than here.
|
||||
[Deprecated="MozfullscreenchangeDeprecatedPrefix"]
|
||||
attribute EventHandler onmozfullscreenchange;
|
||||
[Deprecated="MozfullscreenerrorDeprecatedPrefix"]
|
||||
attribute EventHandler onmozfullscreenerror;
|
||||
|
||||
// CSS-Animation and CSS-Transition handlers.
|
||||
|
|
|
@ -222,7 +222,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
|||
nullptr, // aCallbacks
|
||||
aLoadFlags,
|
||||
ios);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
|
||||
} else {
|
||||
// We must have a loadGroup with a load context for the principal to
|
||||
// traverse the channel correctly.
|
||||
|
@ -262,7 +262,7 @@ ChannelFromScriptURL(nsIPrincipal* principal,
|
|||
ios);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
||||
if (cspEventListener) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
commit 6a8e28db3cbff837570f93881e6e4f7ff4d5fb25
|
||||
Author: Yoshito Umaoka <yoshito_umaoka@us.ibm.com>
|
||||
Date: Tue Oct 30 08:52:31 2018 -0400
|
||||
|
||||
ICU-20245: tzdata2018g updates. Also added tzdata2018f release files missed previously.
|
|
@ -1,10 +0,0 @@
|
|||
Path: 44
|
||||
URL: https://ssl.icu-project.org/repos/icu/data/trunk/tzdata/icunew/2018e/44
|
||||
Relative URL: ^/data/trunk/tzdata/icunew/2018e/44
|
||||
Repository Root: https://ssl.icu-project.org/repos/icu
|
||||
Repository UUID: 251d0590-4201-4cf1-90de-194747b24ca1
|
||||
Node Kind: directory
|
||||
Last Changed Author: yoshito
|
||||
Last Changed Rev: 41324
|
||||
Last Changed Date: 2018-05-04 22:02:44 +0000 (Fri, 04 May 2018)
|
||||
|
|
@ -0,0 +1 @@
|
|||
2018g
|
Двоичные данные
intl/tzdata/source/be/metaZones.res
Двоичные данные
intl/tzdata/source/be/metaZones.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/be/windowsZones.res
Двоичные данные
intl/tzdata/source/be/windowsZones.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/be/zoneinfo64.res
Двоичные данные
intl/tzdata/source/be/zoneinfo64.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/ee/metaZones.res
Двоичные данные
intl/tzdata/source/ee/metaZones.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/ee/windowsZones.res
Двоичные данные
intl/tzdata/source/ee/windowsZones.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/ee/zoneinfo64.res
Двоичные данные
intl/tzdata/source/ee/zoneinfo64.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/le/metaZones.res
Двоичные данные
intl/tzdata/source/le/metaZones.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/le/windowsZones.res
Двоичные данные
intl/tzdata/source/le/windowsZones.res
Двоичный файл не отображается.
Двоичные данные
intl/tzdata/source/le/zoneinfo64.res
Двоичные данные
intl/tzdata/source/le/zoneinfo64.res
Двоичный файл не отображается.
|
@ -813,6 +813,11 @@ metaZones:table(nofallback){
|
|||
{
|
||||
"Europe_Western",
|
||||
"1985-12-31 23:00",
|
||||
"2018-10-26 23:00",
|
||||
}
|
||||
{
|
||||
"Europe_Central",
|
||||
"2018-10-26 23:00",
|
||||
"9999-12-31 23:59",
|
||||
}
|
||||
}
|
||||
|
@ -862,6 +867,11 @@ metaZones:table(nofallback){
|
|||
{
|
||||
"Europe_Western",
|
||||
"1976-04-14 01:00",
|
||||
"2018-10-26 23:00",
|
||||
}
|
||||
{
|
||||
"Europe_Central",
|
||||
"2018-10-26 23:00",
|
||||
"9999-12-31 23:59",
|
||||
}
|
||||
}
|
||||
|
@ -2559,7 +2569,7 @@ metaZones:table(nofallback){
|
|||
{
|
||||
"Casey",
|
||||
"2016-10-21 16:00",
|
||||
"2016-03-10 17:00",
|
||||
"2018-03-10 17:00",
|
||||
}
|
||||
{
|
||||
"Australia_Western",
|
||||
|
@ -3132,11 +3142,11 @@ metaZones:table(nofallback){
|
|||
{
|
||||
"Pyongyang",
|
||||
"2015-08-14 15:00",
|
||||
"2018-05-05 08:30",
|
||||
"2018-05-04 15:00",
|
||||
}
|
||||
{
|
||||
"Korea",
|
||||
"2018-05-05 08:30",
|
||||
"2018-05-04 15:00",
|
||||
"9999-12-31 23:59",
|
||||
}
|
||||
}
|
||||
|
@ -3992,6 +4002,11 @@ metaZones:table(nofallback){
|
|||
{
|
||||
"Moscow",
|
||||
"1992-03-28 22:00",
|
||||
"2018-10-27 23:00",
|
||||
}
|
||||
{
|
||||
"Volgograd",
|
||||
"2018-10-27 23:00",
|
||||
"9999-12-31 23:59",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -287,7 +287,7 @@ windowsZones:table(nofallback){
|
|||
}
|
||||
"GTB Standard Time"{
|
||||
001{"Europe/Bucharest"}
|
||||
CY{"Asia/Nicosia"}
|
||||
CY{"Asia/Famagusta Asia/Nicosia"}
|
||||
GR{"Europe/Athens"}
|
||||
RO{"Europe/Bucharest"}
|
||||
}
|
||||
|
@ -580,6 +580,10 @@ windowsZones:table(nofallback){
|
|||
001{"Pacific/Apia"}
|
||||
WS{"Pacific/Apia"}
|
||||
}
|
||||
"Sao Tome Standard Time"{
|
||||
001{"Africa/Sao_Tome"}
|
||||
ST{"Africa/Sao_Tome"}
|
||||
}
|
||||
"Saratov Standard Time"{
|
||||
001{"Europe/Saratov"}
|
||||
RU{"Europe/Saratov"}
|
||||
|
@ -654,7 +658,6 @@ windowsZones:table(nofallback){
|
|||
}
|
||||
"Turkey Standard Time"{
|
||||
001{"Europe/Istanbul"}
|
||||
CY{"Asia/Famagusta"}
|
||||
TR{"Europe/Istanbul"}
|
||||
}
|
||||
"Turks And Caicos Standard Time"{
|
||||
|
@ -746,7 +749,6 @@ windowsZones:table(nofallback){
|
|||
GQ{"Africa/Malabo"}
|
||||
NE{"Africa/Niamey"}
|
||||
NG{"Africa/Lagos"}
|
||||
ST{"Africa/Sao_Tome"}
|
||||
TD{"Africa/Ndjamena"}
|
||||
TN{"Africa/Tunis"}
|
||||
ZZ{"Etc/GMT-1"}
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
// License & terms of use: http://www.unicode.org/copyright.html#License
|
||||
//---------------------------------------------------------
|
||||
// Build tool: tz2icu
|
||||
// Build date: Fri May 4 16:06:17 2018
|
||||
// Build date: Tue Oct 30 03:17:32 2018
|
||||
// tz database: ftp://ftp.iana.org/tz/
|
||||
// tz version: 2018e
|
||||
// ICU version: 61.1
|
||||
// tz version: 2018g
|
||||
// ICU version: 63.1
|
||||
//---------------------------------------------------------
|
||||
// >> !!! >> THIS IS A MACHINE-GENERATED FILE << !!! <<
|
||||
// >> !!! >>> DO NOT EDIT <<< !!! <<
|
||||
//---------------------------------------------------------
|
||||
|
||||
zoneinfo64:table(nofallback) {
|
||||
TZVersion { "2018e" }
|
||||
TZVersion { "2018g" }
|
||||
Zones:array {
|
||||
/* ACT */ :int { 354 } //Z#0
|
||||
/* AET */ :int { 366 } //Z#1
|
||||
|
@ -59,13 +59,9 @@ zoneinfo64:table(nofallback) {
|
|||
links:intvector { 3, 18, 400 }
|
||||
} //Z#18
|
||||
/* Africa/Casablanca */ :table {
|
||||
trans:intvector { -1773012580, -956361600, -950490000, -942019200, -761187600, -617241600, -605149200, -81432000, -71110800, 141264000, 147222000, 199756800, 207702000, 231292800, 244249200, 265507200, 271033200, 448243200, 504918000, 1212278400, 1220223600, 1243814400, 1250809200, 1272758400, 1281222000, 1301788800, 1312066800, 1335664800, 1342749600, 1345428000, 1348970400, 1367114400, 1373162400, 1376100000, 1382839200, 1396144800, 1403920800, 1406944800, 1414288800, 1427594400, 1434247200, 1437271200, 1445738400, 1459044000, 1465092000, 1468116000, 1477792800, 1490493600, 1495332000, 1498960800, 1509242400, 1521943200, 1526176800, 1529200800, 1540692000, 1553997600, 1557021600, 1560045600, 1572141600, 1585447200, 1587261600, 1590285600, 1603591200, 1616896800, 1618106400, 1621130400, 1635645600, 1651975200, 1667095200, 1682215200, 1698544800, 1713060000, 1729994400, 1743904800, 1761444000, 1774749600, 1792893600, 1806199200, 1824948000, 1837648800, 1856397600, 1869098400, 1887847200, 1901152800, 1919296800, 1932602400, 1950746400, 1964052000, 1982800800, 1995501600, 2014250400, 2026951200, 2045700000, 2058400800, 2077149600, 2090455200, 2107994400, 2121904800, 2138234400 }
|
||||
transPost32:intvector { 0, -2141612896, 0, -2122864096 }
|
||||
trans:intvector { -1773012580, -956361600, -950490000, -942019200, -761187600, -617241600, -605149200, -81432000, -71110800, 141264000, 147222000, 199756800, 207702000, 231292800, 244249200, 265507200, 271033200, 448243200, 504918000, 1212278400, 1220223600, 1243814400, 1250809200, 1272758400, 1281222000, 1301788800, 1312066800, 1335664800, 1342749600, 1345428000, 1348970400, 1367114400, 1373162400, 1376100000, 1382839200, 1396144800, 1403920800, 1406944800, 1414288800, 1427594400, 1434247200, 1437271200, 1445738400, 1459044000, 1465092000, 1468116000, 1477792800, 1490493600, 1495332000, 1498960800, 1509242400, 1521943200, 1526176800, 1529200800, 1540594800 }
|
||||
typeOffsets:intvector { -1820, 0, 0, 0, 0, 3600, 3600, 0 }
|
||||
typeMap:bin { "0102010201020102010201020102010201030102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" }
|
||||
finalRule { "Morocco" }
|
||||
finalRaw:int { 0 }
|
||||
finalYear:int { 2039 }
|
||||
typeMap:bin { "01020102010201020102010201020102010301020102010201020102010201020102010201020102010201020102010201020102010203" }
|
||||
} //Z#19
|
||||
/* Africa/Ceuta */ :table {
|
||||
transPre32:intvector { -1, 2117514496 }
|
||||
|
@ -82,13 +78,9 @@ zoneinfo64:table(nofallback) {
|
|||
/* Africa/Djibouti */ :int { 48 } //Z#24
|
||||
/* Africa/Douala */ :int { 36 } //Z#25
|
||||
/* Africa/El_Aaiun */ :table {
|
||||
trans:intvector { -1136070432, 198291600, 199756800, 207702000, 231292800, 244249200, 265507200, 271033200, 1212278400, 1220223600, 1243814400, 1250809200, 1272758400, 1281222000, 1301788800, 1312066800, 1335664800, 1342749600, 1345428000, 1348970400, 1367114400, 1373162400, 1376100000, 1382839200, 1396144800, 1403920800, 1406944800, 1414288800, 1427594400, 1434247200, 1437271200, 1445738400, 1459044000, 1465092000, 1468116000, 1477792800, 1490493600, 1495332000, 1498960800, 1509242400, 1521943200, 1526176800, 1529200800, 1540692000, 1553997600, 1557021600, 1560045600, 1572141600, 1585447200, 1587261600, 1590285600, 1603591200, 1616896800, 1618106400, 1621130400, 1635645600, 1651975200, 1667095200, 1682215200, 1698544800, 1713060000, 1729994400, 1743904800, 1761444000, 1774749600, 1792893600, 1806199200, 1824948000, 1837648800, 1856397600, 1869098400, 1887847200, 1901152800, 1919296800, 1932602400, 1950746400, 1964052000, 1982800800, 1995501600, 2014250400, 2026951200, 2045700000, 2058400800, 2077149600, 2090455200, 2107994400, 2121904800, 2138234400 }
|
||||
transPost32:intvector { 0, -2141612896, 0, -2122864096 }
|
||||
typeOffsets:intvector { -3168, 0, -3600, 0, 0, 0, 0, 3600 }
|
||||
typeMap:bin { "010203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302030203020302" }
|
||||
finalRule { "Morocco" }
|
||||
finalRaw:int { 0 }
|
||||
finalYear:int { 2039 }
|
||||
trans:intvector { -1136070432, 198291600, 199756800, 207702000, 231292800, 244249200, 265507200, 271033200, 1212278400, 1220223600, 1243814400, 1250809200, 1272758400, 1281222000, 1301788800, 1312066800, 1335664800, 1342749600, 1345428000, 1348970400, 1367114400, 1373162400, 1376100000, 1382839200, 1396144800, 1403920800, 1406944800, 1414288800, 1427594400, 1434247200, 1437271200, 1445738400, 1459044000, 1465092000, 1468116000, 1477792800, 1490493600, 1495332000, 1498960800, 1509242400, 1521943200, 1526176800, 1529200800, 1540594800 }
|
||||
typeOffsets:intvector { -3168, 0, -3600, 0, 0, 0, 0, 3600, 3600, 0 }
|
||||
typeMap:bin { "0102030203020302030203020302030203020302030203020302030203020302030203020302030203020304" }
|
||||
} //Z#26
|
||||
/* Africa/Freetown */ :int { 5 } //Z#27
|
||||
/* Africa/Gaborone */ :int { 43 } //Z#28
|
||||
|
@ -1030,12 +1022,12 @@ zoneinfo64:table(nofallback) {
|
|||
typeMap:bin { "010201020102010201020102010201020102010201020102010201020103" }
|
||||
} //Z#199
|
||||
/* America/Santiago */ :table {
|
||||
trans:intvector { -1892661434, -1688410800, -1619205434, -1593806400, -1335986234, -1317585600, -1304362800, -1286049600, -1272826800, -1254513600, -1241290800, -1222977600, -1209754800, -1191355200, -1178132400, -870552000, -865278000, -740520000, -736376400, -718056000, -713649600, -36619200, -23922000, -3355200, 7527600, 24465600, 37767600, 55915200, 69217200, 87969600, 100666800, 118209600, 132116400, 150868800, 163566000, 182318400, 195620400, 213768000, 227070000, 245217600, 258519600, 277272000, 289969200, 308721600, 321418800, 340171200, 353473200, 371620800, 384922800, 403070400, 416372400, 434520000, 447822000, 466574400, 479271600, 498024000, 510721200, 529473600, 545194800, 560923200, 574225200, 592372800, 605674800, 624427200, 637124400, 653457600, 668574000, 687326400, 700628400, 718776000, 732078000, 750225600, 763527600, 781675200, 794977200, 813729600, 826426800, 845179200, 859690800, 876628800, 889930800, 906868800, 923194800, 939528000, 952830000, 971582400, 984279600, 1003032000, 1015729200, 1034481600, 1047178800, 1065931200, 1079233200, 1097380800, 1110682800, 1128830400, 1142132400, 1160884800, 1173582000, 1192334400, 1206846000, 1223784000, 1237086000, 1255233600, 1270350000, 1286683200, 1304823600, 1313899200, 1335668400, 1346558400, 1367118000, 1378612800, 1398567600, 1410062400, 1463281200, 1471147200 }
|
||||
trans:intvector { -1892661434, -1688410800, -1619205434, -1593806400, -1335986234, -1317585600, -1304362800, -1286049600, -1272826800, -1254513600, -1241290800, -1222977600, -1209754800, -1191355200, -1178132400, -870552000, -865278000, -740520000, -736376400, -718056000, -713649600, -36619200, -23922000, -3355200, 7527600, 24465600, 37767600, 55915200, 69217200, 87969600, 100666800, 118209600, 132116400, 150868800, 163566000, 182318400, 195620400, 213768000, 227070000, 245217600, 258519600, 277272000, 289969200, 308721600, 321418800, 340171200, 353473200, 371620800, 384922800, 403070400, 416372400, 434520000, 447822000, 466574400, 479271600, 498024000, 510721200, 529473600, 545194800, 560923200, 574225200, 592372800, 605674800, 624427200, 637124400, 653457600, 668574000, 687326400, 700628400, 718776000, 732078000, 750225600, 763527600, 781675200, 794977200, 813729600, 826426800, 845179200, 859690800, 876628800, 889930800, 906868800, 923194800, 939528000, 952830000, 971582400, 984279600, 1003032000, 1015729200, 1034481600, 1047178800, 1065931200, 1079233200, 1097380800, 1110682800, 1128830400, 1142132400, 1160884800, 1173582000, 1192334400, 1206846000, 1223784000, 1237086000, 1255233600, 1270350000, 1286683200, 1304823600, 1313899200, 1335668400, 1346558400, 1367118000, 1378612800, 1398567600, 1410062400, 1463281200, 1471147200, 1494730800, 1502596800, 1526180400, 1534046400, 1554606000, 1567915200 }
|
||||
typeOffsets:intvector { -16966, 0, -18000, 0, -18000, 3600, -14400, 0, -14400, 3600 }
|
||||
typeMap:bin { "0100030002010201020102010201030103040301030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304" }
|
||||
typeMap:bin { "0100030002010201020102010201030103040301030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304" }
|
||||
finalRule { "Chile" }
|
||||
finalRaw:int { -14400 }
|
||||
finalYear:int { 2017 }
|
||||
finalYear:int { 2020 }
|
||||
links:intvector { 200, 392 }
|
||||
} //Z#200
|
||||
/* America/Santo_Domingo */ :table {
|
||||
|
@ -1498,9 +1490,9 @@ zoneinfo64:table(nofallback) {
|
|||
/* Asia/Kuwait */ :int { 308 } //Z#290
|
||||
/* Asia/Macao */ :int { 292 } //Z#291
|
||||
/* Asia/Macau */ :table {
|
||||
trans:intvector { -1830412800, -277360200, -257405400, -245910600, -225955800, -214473600, -194506200, -182406600, -163056600, -150969600, -131619600, -117088200, -101367000, -85638600, -69312600, -53584200, -37863000, -22134600, -6413400, 9315000, 25036200, 40764600, 56485800, 72201600, 87922800, 103651200, 119977200, 135705600, 151439400, 167167800, 182889000, 198617400, 214338600, 230067000, 245788200, 261504000, 277225200, 292953600, 309279600, 325008000, 340729200 }
|
||||
typeOffsets:intvector { 27260, 0, 28800, 0, 28800, 3600 }
|
||||
typeMap:bin { "0102010201020102010201020102010201020102010201020102010201020102010201020102010201" }
|
||||
trans:intvector { -2056692850, -884509200, -873280800, -855918000, -841744800, -828529200, -765363600, -747046800, -733827600, -716461200, -697021200, -683715600, -667990800, -654771600, -636627600, -623322000, -605178000, -591872400, -573642000, -559818000, -541674000, -528368400, -510224400, -498128400, -478774800, -466678800, -446720400, -435229200, -415258200, -403158600, -383808600, -371709000, -352359000, -340259400, -320909400, -308809800, -288855000, -277360200, -257405400, -245910600, -225955800, -213856200, -194506200, -182406600, -163056600, -148537800, -132820200, -117088200, -101370600, -85638600, -69312600, -53584200, -37863000, -22134600, -6413400, 9315000, 25036200, 40764600, 56485800, 72214200, 88540200, 104268600, 119989800, 126041400, 151439400, 167167800, 182889000, 198617400, 214338600, 295385400, 309292200 }
|
||||
typeOffsets:intvector { 27250, 0, 28800, 0, 28800, 3600, 32400, 0, 32400, 3600 }
|
||||
typeMap:bin { "0103040304030102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" }
|
||||
links:intvector { 291, 292 }
|
||||
} //Z#292
|
||||
/* Asia/Magadan */ :table {
|
||||
|
@ -1557,7 +1549,7 @@ zoneinfo64:table(nofallback) {
|
|||
typeMap:bin { "02040203020301" }
|
||||
} //Z#303
|
||||
/* Asia/Pyongyang */ :table {
|
||||
trans:intvector { -1948782180, -1830414600, 1439564400, 1525447800 }
|
||||
trans:intvector { -1948782180, -1830414600, 1439564400, 1525446000 }
|
||||
typeOffsets:intvector { 30180, 0, 30600, 0, 32400, 0 }
|
||||
typeMap:bin { "01020102" }
|
||||
} //Z#304
|
||||
|
@ -1598,9 +1590,9 @@ zoneinfo64:table(nofallback) {
|
|||
} //Z#312
|
||||
/* Asia/Shanghai */ :table {
|
||||
transPre32:intvector { -1, 2117485353 }
|
||||
trans:intvector { -933494400, -923130000, -908784000, -891594000, 515520000, 527007600, 545155200, 558457200, 576604800, 589906800, 608659200, 621961200, 640108800, 653410800, 671558400, 684860400 }
|
||||
trans:intvector { -933667200, -922093200, -908870400, -888829200, -881049600, -767869200, -745833600, -733827600, -716889600, -699613200, -683884800, -670669200, -652348800, -650019600, 515527200, 527014800, 545162400, 558464400, 577216800, 589914000, 608666400, 621968400, 640116000, 653418000, 671565600, 684867600 }
|
||||
typeOffsets:intvector { 29143, 0, 28800, 0, 28800, 3600 }
|
||||
typeMap:bin { "0102010201020102010201020102010201" }
|
||||
typeMap:bin { "010201020102010201020102010201020102010201020102010201" }
|
||||
links:intvector { 258, 259, 269, 313, 382, 546 }
|
||||
} //Z#313
|
||||
/* Asia/Singapore */ :table {
|
||||
|
@ -1650,7 +1642,7 @@ zoneinfo64:table(nofallback) {
|
|||
} //Z#322
|
||||
/* Asia/Tokyo */ :table {
|
||||
transPre32:intvector { -1, 1707254896 }
|
||||
trans:intvector { -683802000, -672314400, -654771600, -640864800, -620298000, -609415200, -588848400, -577965600 }
|
||||
trans:intvector { -683802000, -672310800, -654771600, -640861200, -620298000, -609411600, -588848400, -577962000 }
|
||||
typeOffsets:intvector { 33539, 0, 32400, 0, 32400, 3600 }
|
||||
typeMap:bin { "010201020102010201" }
|
||||
links:intvector { 323, 527, 529 }
|
||||
|
@ -2406,9 +2398,9 @@ zoneinfo64:table(nofallback) {
|
|||
finalYear:int { 2004 }
|
||||
} //Z#495
|
||||
/* Europe/Volgograd */ :table {
|
||||
trans:intvector { -1577761060, -1247540400, 354916800, 370724400, 386452800, 402260400, 417988800, 433796400, 449611200, 465343200, 481068000, 496792800, 512517600, 528242400, 543967200, 559692000, 575416800, 591145200, 606870000, 622594800, 638319600, 654649200, 670374000, 701820000, 717548400, 733273200, 748998000, 764722800, 780447600, 796172400, 811897200, 828226800, 846370800, 859676400, 877820400, 891126000, 909270000, 922575600, 941324400, 954025200, 972774000, 985474800, 1004223600, 1017529200, 1035673200, 1048978800, 1067122800, 1080428400, 1099177200, 1111878000, 1130626800, 1143327600, 1162076400, 1174777200, 1193526000, 1206831600, 1224975600, 1238281200, 1256425200, 1269730800, 1288479600, 1301180400, 1414274400 }
|
||||
trans:intvector { -1577761060, -1247540400, 354916800, 370724400, 386452800, 402260400, 417988800, 433796400, 449611200, 465343200, 481068000, 496792800, 512517600, 528242400, 543967200, 559692000, 575416800, 591145200, 606870000, 622594800, 638319600, 654649200, 670374000, 701820000, 717548400, 733273200, 748998000, 764722800, 780447600, 796172400, 811897200, 828226800, 846370800, 859676400, 877820400, 891126000, 909270000, 922575600, 941324400, 954025200, 972774000, 985474800, 1004223600, 1017529200, 1035673200, 1048978800, 1067122800, 1080428400, 1099177200, 1111878000, 1130626800, 1143327600, 1162076400, 1174777200, 1193526000, 1206831600, 1224975600, 1238281200, 1256425200, 1269730800, 1288479600, 1301180400, 1414274400, 1540681200 }
|
||||
typeOffsets:intvector { 10660, 0, 10800, 0, 10800, 3600, 14400, 0, 14400, 3600 }
|
||||
typeMap:bin { "010304030403040304030403040304030201020102010302010201020102010201020102010201020102010201020102010201020102010201020102010301" }
|
||||
typeMap:bin { "01030403040304030403040304030403020102010201030201020102010201020102010201020102010201020102010201020102010201020102010201030103" }
|
||||
} //Z#496
|
||||
/* Europe/Warsaw */ :table {
|
||||
trans:intvector { -1717032240, -1693706400, -1680483600, -1663455600, -1650150000, -1632006000, -1618700400, -1600473600, -1587168000, -1501725600, -931734000, -857257200, -844556400, -828226800, -812502000, -796608000, -778726800, -762660000, -748486800, -733273200, -715215600, -701910000, -684975600, -670460400, -654130800, -639010800, -397094400, -386812800, -371088000, -355363200, -334195200, -323308800, -307584000, -291859200, -271296000, -260409600, -239846400, -228960000, -208396800, -197510400, -176342400, -166060800, 228873600, 243993600, 260323200, 276048000, 291772800, 307497600, 323827200, 338947200, 354672000, 370396800, 386121600, 401846400, 417571200, 433296000, 449020800, 465350400, 481075200, 496800000, 512524800, 528249600, 543974400, 559699200, 575427600, 591152400, 606877200, 622602000, 638326800, 654656400, 670381200, 686106000, 701830800, 717555600, 733280400, 749005200, 764730000, 780454800, 796179600, 811904400, 828234000, 846378000 }
|
||||
|
@ -2590,12 +2582,12 @@ zoneinfo64:table(nofallback) {
|
|||
links:intvector { 554, 589, 592 }
|
||||
} //Z#554
|
||||
/* Pacific/Easter */ :table {
|
||||
trans:intvector { -1178124152, -36619200, -23922000, -3355200, 7527600, 24465600, 37767600, 55915200, 69217200, 87969600, 100666800, 118209600, 132116400, 150868800, 163566000, 182318400, 195620400, 213768000, 227070000, 245217600, 258519600, 277272000, 289969200, 308721600, 321418800, 340171200, 353473200, 371620800, 384922800, 403070400, 416372400, 434520000, 447822000, 466574400, 479271600, 498024000, 510721200, 529473600, 545194800, 560923200, 574225200, 592372800, 605674800, 624427200, 637124400, 653457600, 668574000, 687326400, 700628400, 718776000, 732078000, 750225600, 763527600, 781675200, 794977200, 813729600, 826426800, 845179200, 859690800, 876628800, 889930800, 906868800, 923194800, 939528000, 952830000, 971582400, 984279600, 1003032000, 1015729200, 1034481600, 1047178800, 1065931200, 1079233200, 1097380800, 1110682800, 1128830400, 1142132400, 1160884800, 1173582000, 1192334400, 1206846000, 1223784000, 1237086000, 1255233600, 1270350000, 1286683200, 1304823600, 1313899200, 1335668400, 1346558400, 1367118000, 1378612800, 1398567600, 1410062400, 1463281200, 1471147200 }
|
||||
trans:intvector { -1178124152, -36619200, -23922000, -3355200, 7527600, 24465600, 37767600, 55915200, 69217200, 87969600, 100666800, 118209600, 132116400, 150868800, 163566000, 182318400, 195620400, 213768000, 227070000, 245217600, 258519600, 277272000, 289969200, 308721600, 321418800, 340171200, 353473200, 371620800, 384922800, 403070400, 416372400, 434520000, 447822000, 466574400, 479271600, 498024000, 510721200, 529473600, 545194800, 560923200, 574225200, 592372800, 605674800, 624427200, 637124400, 653457600, 668574000, 687326400, 700628400, 718776000, 732078000, 750225600, 763527600, 781675200, 794977200, 813729600, 826426800, 845179200, 859690800, 876628800, 889930800, 906868800, 923194800, 939528000, 952830000, 971582400, 984279600, 1003032000, 1015729200, 1034481600, 1047178800, 1065931200, 1079233200, 1097380800, 1110682800, 1128830400, 1142132400, 1160884800, 1173582000, 1192334400, 1206846000, 1223784000, 1237086000, 1255233600, 1270350000, 1286683200, 1304823600, 1313899200, 1335668400, 1346558400, 1367118000, 1378612800, 1398567600, 1410062400, 1463281200, 1471147200, 1494730800, 1502596800, 1526180400, 1534046400, 1554606000, 1567915200 }
|
||||
typeOffsets:intvector { -26248, 0, -25200, 0, -25200, 3600, -21600, 0, -21600, 3600 }
|
||||
typeMap:bin { "010201020102010201020102010201020102010201020102010201020304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304" }
|
||||
typeMap:bin { "010201020102010201020102010201020102010201020102010201020304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304030403040304" }
|
||||
finalRule { "Chile" }
|
||||
finalRaw:int { -21600 }
|
||||
finalYear:int { 2017 }
|
||||
finalYear:int { 2020 }
|
||||
links:intvector { 393, 555 }
|
||||
} //Z#555
|
||||
/* Pacific/Efate */ :table {
|
||||
|
@ -3100,7 +3092,7 @@ zoneinfo64:table(nofallback) {
|
|||
8, -30, -1, 9900, 1, 3, 1, -1, 9900, 1, 3600
|
||||
} //_#7
|
||||
Chile:intvector {
|
||||
7, 9, -1, 14400, 2, 4, 9, -1, 10800, 2, 3600
|
||||
8, 2, -1, 14400, 2, 3, 2, -1, 10800, 2, 3600
|
||||
} //_#8
|
||||
Cuba:intvector {
|
||||
2, 8, -1, 0, 1, 10, 1, -1, 0, 1, 3600
|
||||
|
@ -3115,7 +3107,7 @@ zoneinfo64:table(nofallback) {
|
|||
9, -31, -1, 3600, 2, 2, -31, -1, 3600, 2, -3600
|
||||
} //_#12
|
||||
Fiji:intvector {
|
||||
10, 1, -1, 7200, 0, 0, 14, -1, 10800, 0, 3600
|
||||
10, 1, -1, 7200, 0, 0, 13, -1, 10800, 0, 3600
|
||||
} //_#13
|
||||
Haiti:intvector {
|
||||
2, 8, -1, 7200, 0, 10, 1, -1, 7200, 0, 3600
|
||||
|
@ -3138,39 +3130,36 @@ zoneinfo64:table(nofallback) {
|
|||
Moldova:intvector {
|
||||
2, -31, -1, 7200, 0, 9, -31, -1, 10800, 0, 3600
|
||||
} //_#20
|
||||
Morocco:intvector {
|
||||
2, -31, -1, 7200, 0, 9, -31, -1, 10800, 0, 3600
|
||||
} //_#21
|
||||
NZ:intvector {
|
||||
8, -30, -1, 7200, 1, 3, 1, -1, 7200, 1, 3600
|
||||
} //_#22
|
||||
} //_#21
|
||||
Palestine:intvector {
|
||||
2, 22, -7, 3600, 0, 9, -31, -7, 3600, 0, 3600
|
||||
} //_#23
|
||||
} //_#22
|
||||
Para:intvector {
|
||||
9, 1, -1, 0, 0, 2, 22, -1, 0, 0, 3600
|
||||
} //_#24
|
||||
} //_#23
|
||||
Syria:intvector {
|
||||
2, -31, -6, 0, 0, 9, -31, -6, 0, 0, 3600
|
||||
} //_#25
|
||||
} //_#24
|
||||
SystemV:intvector {
|
||||
3, -30, -1, 7200, 0, 9, -31, -1, 7200, 0, 3600
|
||||
} //_#26
|
||||
} //_#25
|
||||
Thule:intvector {
|
||||
2, 8, -1, 7200, 0, 10, 1, -1, 7200, 0, 3600
|
||||
} //_#27
|
||||
} //_#26
|
||||
Troll:intvector {
|
||||
2, -31, -1, 3600, 2, 9, -31, -1, 3600, 2, 7200
|
||||
} //_#28
|
||||
} //_#27
|
||||
US:intvector {
|
||||
2, 8, -1, 7200, 0, 10, 1, -1, 7200, 0, 3600
|
||||
} //_#29
|
||||
} //_#28
|
||||
WS:intvector {
|
||||
8, -30, -1, 10800, 0, 3, 1, -1, 14400, 0, 3600
|
||||
} //_#30
|
||||
} //_#29
|
||||
Zion:intvector {
|
||||
2, 23, -6, 7200, 0, 9, -31, -1, 7200, 0, 3600
|
||||
} //_#31
|
||||
} //_#30
|
||||
}
|
||||
Regions:array {
|
||||
"AU", //Z#0 ACT
|
||||
|
|
|
@ -8,11 +8,11 @@ set -e
|
|||
# Usage: update-tzdata.sh <tzdata version>
|
||||
# E.g., for tzdata2016f: update-tzdata.sh 2016f
|
||||
|
||||
# Ensure that $Date$ in the checked-out svn files expands timezone-agnostically,
|
||||
# Ensure that $Date$ in the checked-out git files expands timezone-agnostically,
|
||||
# so that this script's behavior is consistent when run from any time zone.
|
||||
export TZ=UTC
|
||||
|
||||
# Also ensure SVN-INFO is consistently English.
|
||||
# Also ensure GIT-INFO is consistently English.
|
||||
export LANG=en_US.UTF-8
|
||||
export LANGUAGE=en_US
|
||||
export LC_ALL=en_US.UTF-8
|
||||
|
@ -21,7 +21,7 @@ export LC_ALL=en_US.UTF-8
|
|||
icu_pkg=
|
||||
# Force updates even when current tzdata is newer than the requested version.
|
||||
force=false
|
||||
# Dry run, doesn't run 'svn export' and 'icupkg'.
|
||||
# Dry run, doesn't run 'git clone' and 'icupkg'.
|
||||
dry=false
|
||||
# Compare ICU and local tzdata versions (used by update-icu.sh).
|
||||
check_version=false
|
||||
|
@ -51,11 +51,11 @@ icudata_dir=`dirname "$0"`/../config/external/icu/data
|
|||
icu_dir=`dirname "$0"`/icu
|
||||
tzdata_dir=`dirname "$0"`/tzdata
|
||||
tzdata_files="${tzdata_dir}"/files.txt
|
||||
tzdata_url=https://ssl.icu-project.org/repos/icu/data/trunk/tzdata/icunew/${tzdata_version}/44/
|
||||
tzdata_url=https://github.com/unicode-org/icu-data.git
|
||||
icu_tzdata_version=`grep --only-matching --perl-regexp --regexp="tz version:\s+\K.*$" "${icu_dir}"/source/data/misc/zoneinfo64.txt`
|
||||
local_tzdata_version=
|
||||
if [ -f "${tzdata_dir}"/SVN-INFO ]; then
|
||||
local_tzdata_version=`grep --only-matching --perl-regexp --regexp="^URL: .*tzdata/icunew/\K[0-9a-z]+" "${tzdata_dir}"/SVN-INFO`
|
||||
if [ -f "${tzdata_dir}"/VERSION ]; then
|
||||
local_tzdata_version=`grep --only-matching --perl-regexp --regexp="^\K[0-9a-z]+" "${tzdata_dir}"/VERSION`
|
||||
fi
|
||||
|
||||
# Check ICU and current local tzdata versions.
|
||||
|
@ -120,20 +120,21 @@ else
|
|||
echo "INFO: ICU data file (big endian) not found, skipping..."
|
||||
fi
|
||||
|
||||
# Retrieve tzdata from svn.
|
||||
# Retrieve tzdata from git.
|
||||
if [ $dry = false ]; then
|
||||
echo "INFO: Downloading tzdata${tzdata_version}"
|
||||
|
||||
# Remove intl/tzdata/source, then replace it with a clean export.
|
||||
rm -r "${tzdata_dir}"/source
|
||||
svn export "${tzdata_url}" "${tzdata_dir}"/source
|
||||
fi
|
||||
git clone --depth 1 "${tzdata_url}" "${tzdata_dir}"/source
|
||||
git -C "${tzdata_dir}"/source filter-branch --prune-empty --subdirectory-filter tzdata/icunew/${tzdata_version}/44 HEAD
|
||||
|
||||
# Record `svn info`, eliding the line that changes every time the entire ICU
|
||||
# tzdata repository (not just the path within it we care about) receives a
|
||||
# commit.
|
||||
if [ $dry = false ]; then
|
||||
svn info "${tzdata_url}" | grep --invert-match '^Revision: [[:digit:]]\+$' > "${tzdata_dir}"/SVN-INFO
|
||||
# Record `git log` and the tzdata version.
|
||||
git -C "${tzdata_dir}"/source log -1 > "${tzdata_dir}"/GIT-INFO
|
||||
echo "${tzdata_version}" > "${tzdata_dir}"/VERSION
|
||||
|
||||
# Remove the .git directory.
|
||||
rm -rf "${tzdata_dir}"/source/.git
|
||||
fi
|
||||
|
||||
# Update ICU data.
|
||||
|
@ -163,11 +164,11 @@ if [ $dry = false ]; then
|
|||
update_icu_data "be" "${icudata_file_be}"
|
||||
fi
|
||||
|
||||
hg addremove "${tzdata_dir}/source" "${tzdata_dir}/SVN-INFO" "${icudata_file_le}"
|
||||
hg addremove "${tzdata_dir}/source" "${tzdata_dir}/GIT-INFO" "${tzdata_dir}/VERSION" "${icudata_file_le}"
|
||||
if [ -n "${icudata_file_be}" ]; then
|
||||
hg addremove "${icudata_file_be}"
|
||||
fi
|
||||
|
||||
echo "INFO: Successfully updated tzdata!"
|
||||
echo "INFO: Please run js/src/builtin/make_intl_data.py to update additional time zone files for SpiderMonkey."
|
||||
echo "INFO: Please run js/src/builtin/intl/make_intl_data.py to update additional time zone files for SpiderMonkey."
|
||||
fi
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Generated by make_intl_data.py. DO NOT EDIT.
|
||||
// tzdata version = 2018e
|
||||
// tzdata version = 2018g
|
||||
|
||||
#ifndef builtin_intl_TimeZoneDataGenerated_h
|
||||
#define builtin_intl_TimeZoneDataGenerated_h
|
||||
|
@ -104,6 +104,8 @@ const char* const legacyICUTimeZones[] = {
|
|||
"Canada/East-Saskatchewan",
|
||||
"EAT",
|
||||
"ECT",
|
||||
"Eire--ICU",
|
||||
"Europe/Bratislava--ICU",
|
||||
"IET",
|
||||
"IST",
|
||||
"JST",
|
||||
|
@ -116,6 +118,9 @@ const char* const legacyICUTimeZones[] = {
|
|||
"PST",
|
||||
"SST",
|
||||
"VST",
|
||||
"Africa/Windhoek--ICU",
|
||||
"Europe/Dublin--ICU",
|
||||
"Europe/Prague--ICU",
|
||||
"SystemV/AST4",
|
||||
"SystemV/AST4ADT",
|
||||
"SystemV/CST6",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
// Generated by make_intl_data.py. DO NOT EDIT.
|
||||
// tzdata version = 2018e
|
||||
// tzdata version = 2018g
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
// Generated by make_intl_data.py. DO NOT EDIT.
|
||||
// tzdata version = 2018e
|
||||
// tzdata version = 2018g
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
// Generated by make_intl_data.py. DO NOT EDIT.
|
||||
// tzdata version = 2018e
|
||||
// tzdata version = 2018g
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// |reftest| skip-if(!this.hasOwnProperty("Intl"))
|
||||
|
||||
// Generated by make_intl_data.py. DO NOT EDIT.
|
||||
// tzdata version = 2018e
|
||||
// tzdata version = 2018g
|
||||
|
||||
const tzMapper = [
|
||||
x => x,
|
||||
|
|
|
@ -28,18 +28,15 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
|||
Utils: "resource://gre/modules/sessionstore/Utils.jsm",
|
||||
});
|
||||
|
||||
this.messageManager.addMessageListener("GeckoView:SaveState",
|
||||
this);
|
||||
this.messageManager.addMessageListener("GeckoView:RestoreState",
|
||||
this);
|
||||
this.messageManager.addMessageListener("GeckoView:DOMFullscreenEntered",
|
||||
this);
|
||||
this.messageManager.addMessageListener("GeckoView:DOMFullscreenExited",
|
||||
this);
|
||||
this.messageManager.addMessageListener("GeckoView:ZoomToInput",
|
||||
this);
|
||||
this.messageManager.addMessageListener("GeckoView:SetActive",
|
||||
this);
|
||||
this.messageManager.addMessageListener("GeckoView:RestoreState", this);
|
||||
this.messageManager.addMessageListener("GeckoView:SaveState", this);
|
||||
this.messageManager.addMessageListener("GeckoView:SetActive", this);
|
||||
this.messageManager.addMessageListener("GeckoView:UpdateInitData", this);
|
||||
this.messageManager.addMessageListener("GeckoView:ZoomToInput", this);
|
||||
|
||||
const options = {
|
||||
mozSystemGroup: true,
|
||||
|
@ -245,6 +242,12 @@ class GeckoViewContentChild extends GeckoViewChildModule {
|
|||
content.windowUtils.mediaSuspend = aMsg.data.active ? Ci.nsISuspendedTypes.NONE_SUSPENDED : Ci.nsISuspendedTypes.SUSPENDED_PAUSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case "GeckoView:UpdateInitData":
|
||||
// Provide a hook for native code to detect a transfer.
|
||||
Services.obs.notifyObservers(
|
||||
docShell, "geckoview-content-global-transferred");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,9 @@ var ModuleManager = {
|
|||
module.enabled = initData.modules[name];
|
||||
}
|
||||
}
|
||||
|
||||
// Notify child of the transfer.
|
||||
this._browser.messageManager.sendAsyncMessage(aEvent);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,11 @@ package org.mozilla.geckoview.test
|
|||
import org.mozilla.geckoview.GeckoSession
|
||||
import org.mozilla.geckoview.GeckoSessionSettings
|
||||
import org.mozilla.geckoview.GeckoView
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.ClosedSessionAtStart
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.NullDelegate
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.ReuseSession
|
||||
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI
|
||||
import org.mozilla.geckoview.test.util.Callbacks
|
||||
import org.mozilla.geckoview.test.util.UiThreadUtils
|
||||
|
||||
|
@ -258,6 +260,46 @@ class SessionLifecycleTest : BaseSessionTest() {
|
|||
onLocationCount, equalTo(1))
|
||||
}
|
||||
|
||||
@WithDevToolsAPI
|
||||
@Test fun readFromParcel_focusedInput() {
|
||||
// When an input is focused, make sure SessionTextInput is still active after transferring.
|
||||
mainSession.loadTestPath(INPUTS_PATH)
|
||||
mainSession.waitForPageStop()
|
||||
|
||||
mainSession.evaluateJS("$('#input').focus()")
|
||||
mainSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun restartInput(session: GeckoSession, reason: Int) {
|
||||
assertThat("Reason should be correct",
|
||||
reason, equalTo(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS))
|
||||
}
|
||||
})
|
||||
|
||||
val newSession = sessionRule.createClosedSession()
|
||||
mainSession.toParcel { parcel ->
|
||||
newSession.readFromParcel(parcel)
|
||||
}
|
||||
|
||||
// We generate an extra focus event during transfer.
|
||||
newSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun restartInput(session: GeckoSession, reason: Int) {
|
||||
assertThat("Reason should be correct",
|
||||
reason, equalTo(GeckoSession.TextInputDelegate.RESTART_REASON_FOCUS))
|
||||
}
|
||||
})
|
||||
|
||||
newSession.evaluateJS("$('#input').blur()")
|
||||
newSession.waitUntilCalled(object : Callbacks.TextInputDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun restartInput(session: GeckoSession, reason: Int) {
|
||||
// We generate an extra focus event during transfer.
|
||||
assertThat("Reason should be correct",
|
||||
reason, equalTo(GeckoSession.TextInputDelegate.RESTART_REASON_BLUR))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun testRestoreInstanceState(fromSession: GeckoSession?,
|
||||
ontoSession: GeckoSession?) =
|
||||
GeckoView(InstrumentationRegistry.getTargetContext()).apply {
|
||||
|
|
|
@ -4,10 +4,15 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.IGeckoEditableParent;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
// Interface for GeckoEditable calls from parent to child
|
||||
interface IGeckoEditableChild {
|
||||
// Transfer this child to a new parent.
|
||||
void transferParent(in IGeckoEditableParent parent);
|
||||
|
||||
// Process a key event.
|
||||
void onKeyEvent(int action, int keyCode, int scanCode, int metaState,
|
||||
int keyPressMetaState, long time, int domPrintableKeyValue,
|
||||
|
|
|
@ -11,12 +11,15 @@ import org.mozilla.gecko.IGeckoEditableChild;
|
|||
|
||||
// Interface for GeckoEditable calls from child to parent
|
||||
interface IGeckoEditableParent {
|
||||
// Set the default child to forward events to, when there is no focused child.
|
||||
void setDefaultChild(IGeckoEditableChild child);
|
||||
|
||||
// Notify an IME event of a type defined in GeckoEditableListener.
|
||||
void notifyIME(IGeckoEditableChild child, int type);
|
||||
|
||||
// Notify a change in editor state or type.
|
||||
void notifyIMEContext(int state, String typeHint, String modeHint, String actionHint,
|
||||
int flags);
|
||||
void notifyIMEContext(IBinder token, int state, String typeHint, String modeHint,
|
||||
String actionHint, int flags);
|
||||
|
||||
// Notify a change in editor selection.
|
||||
void onSelectionChange(IBinder token, int start, int end);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
package org.mozilla.gecko.process;
|
||||
|
||||
import org.mozilla.gecko.IGeckoEditableParent;
|
||||
import org.mozilla.gecko.IGeckoEditableChild;
|
||||
|
||||
interface IProcessManager {
|
||||
IGeckoEditableParent getEditableParent(long contentId, long tabId);
|
||||
void getEditableParent(in IGeckoEditableChild child, long contentId, long tabId);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.mozilla.gecko.util.ThreadUtils;
|
|||
import android.graphics.RectF;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
|
@ -29,6 +30,11 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
private static final int NOTIFY_IME_TO_CANCEL_COMPOSITION = 9;
|
||||
|
||||
private final class RemoteChild extends IGeckoEditableChild.Stub {
|
||||
@Override // IGeckoEditableChild
|
||||
public void transferParent(final IGeckoEditableParent editableParent) {
|
||||
GeckoEditableChild.this.transferParent(editableParent);
|
||||
}
|
||||
|
||||
@Override // IGeckoEditableChild
|
||||
public void onKeyEvent(int action, int keyCode, int scanCode, int metaState,
|
||||
int keyPressMetaState, long time, int domPrintableKeyValue,
|
||||
|
@ -70,25 +76,49 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
}
|
||||
}
|
||||
|
||||
private final IGeckoEditableParent mEditableParent;
|
||||
private final IGeckoEditableChild mEditableChild;
|
||||
private final boolean mIsDefault;
|
||||
|
||||
private IGeckoEditableParent mEditableParent;
|
||||
private int mCurrentTextLength; // Used by Gecko thread
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
public GeckoEditableChild(final IGeckoEditableParent editableParent) {
|
||||
mEditableParent = editableParent;
|
||||
private GeckoEditableChild(@Nullable final IGeckoEditableParent editableParent,
|
||||
final boolean isDefault) {
|
||||
mIsDefault = isDefault;
|
||||
|
||||
final IBinder binder = editableParent.asBinder();
|
||||
if (binder.queryLocalInterface(IGeckoEditableParent.class.getName()) != null) {
|
||||
if (editableParent != null &&
|
||||
editableParent.asBinder().queryLocalInterface(
|
||||
IGeckoEditableParent.class.getName()) != null) {
|
||||
// IGeckoEditableParent is local; i.e. we're in the main process.
|
||||
mEditableChild = this;
|
||||
} else {
|
||||
// IGeckoEditableParent is remote; i.e. we're in a content process.
|
||||
mEditableChild = new RemoteChild();
|
||||
}
|
||||
|
||||
if (editableParent != null) {
|
||||
setParent(editableParent);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private void setParent(final IGeckoEditableParent editableParent) {
|
||||
mEditableParent = editableParent;
|
||||
|
||||
if (mIsDefault) {
|
||||
// Tell the parent we're the default child.
|
||||
try {
|
||||
editableParent.setDefaultChild(mEditableChild);
|
||||
} catch (final RemoteException e) {
|
||||
Log.e(LOGTAG, "Failed to set default child", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "proxy") @Override // IGeckoEditableChild
|
||||
public native void transferParent(IGeckoEditableParent editableParent);
|
||||
|
||||
@WrapForJNI(dispatchTo = "proxy") @Override // IGeckoEditableChild
|
||||
public native void onKeyEvent(int action, int keyCode, int scanCode, int metaState,
|
||||
int keyPressMetaState, long time, int domPrintableKeyValue,
|
||||
|
@ -123,10 +153,22 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private boolean hasEditableParent() {
|
||||
if (mEditableParent != null) {
|
||||
return true;
|
||||
}
|
||||
Log.w(LOGTAG, "No editable parent");
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // IInterface
|
||||
public IBinder asBinder() {
|
||||
// Return the GeckoEditableParent's binder as our binder for comparison purposes.
|
||||
return mEditableParent.asBinder();
|
||||
// Return the GeckoEditableParent's binder as fallback for comparison purposes.
|
||||
return mEditableChild != this
|
||||
? mEditableChild.asBinder()
|
||||
: hasEditableParent()
|
||||
? mEditableParent.asBinder() : null;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
|
@ -135,6 +177,9 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "notifyIME(" + type + ")");
|
||||
}
|
||||
if (!hasEditableParent()) {
|
||||
return;
|
||||
}
|
||||
if (type == NOTIFY_IME_TO_CANCEL_COMPOSITION) {
|
||||
// Composition should have been canceled on the parent side through text
|
||||
// update notifications. We cannot verify that here because we don't
|
||||
|
@ -161,9 +206,13 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
typeHint + "\", \"" + modeHint + "\", \"" + actionHint +
|
||||
"\", 0x" + Integer.toHexString(flags) + ")");
|
||||
}
|
||||
if (!hasEditableParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mEditableParent.notifyIMEContext(state, typeHint, modeHint, actionHint, flags);
|
||||
mEditableParent.notifyIMEContext(mEditableChild.asBinder(), state, typeHint,
|
||||
modeHint, actionHint, flags);
|
||||
} catch (final RemoteException e) {
|
||||
Log.e(LOGTAG, "Remote call failed", e);
|
||||
}
|
||||
|
@ -175,6 +224,9 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "onSelectionChange(" + start + ", " + end + ")");
|
||||
}
|
||||
if (!hasEditableParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int currentLength = mCurrentTextLength;
|
||||
if (start < 0 || start > currentLength || end < 0 || end > currentLength) {
|
||||
|
@ -195,6 +247,9 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
Log.d(LOGTAG, "onTextChange(" + text + ", " + start + ", " +
|
||||
unboundedOldEnd + ", " + unboundedNewEnd + ")");
|
||||
}
|
||||
if (!hasEditableParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (start < 0 || start > unboundedOldEnd) {
|
||||
Log.e(LOGTAG, "invalid text notification range: " +
|
||||
|
@ -231,6 +286,9 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
.append("repeatCount=").append(event.getRepeatCount()).append(")");
|
||||
Log.d(LOGTAG, sb.toString());
|
||||
}
|
||||
if (!hasEditableParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mEditableParent.onDefaultKeyEvent(mEditableChild.asBinder(), event);
|
||||
|
@ -246,6 +304,9 @@ public final class GeckoEditableChild extends JNIObject implements IGeckoEditabl
|
|||
ThreadUtils.assertOnGeckoThread();
|
||||
Log.d(LOGTAG, "updateCompositionRects(rects.length = " + rects.length + ")");
|
||||
}
|
||||
if (!hasEditableParent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
mEditableParent.updateCompositionRects(mEditableChild.asBinder(), rects);
|
||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.gecko.process;
|
|||
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
import org.mozilla.gecko.IGeckoEditableChild;
|
||||
import org.mozilla.gecko.IGeckoEditableParent;
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
@ -31,13 +32,24 @@ public final class GeckoProcessManager extends IProcessManager.Stub {
|
|||
return INSTANCE;
|
||||
}
|
||||
|
||||
@WrapForJNI(stubName = "GetEditableParent")
|
||||
private static native IGeckoEditableParent nativeGetEditableParent(long contentId,
|
||||
long tabId);
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void setEditableChildParent(final IGeckoEditableChild child,
|
||||
final IGeckoEditableParent parent) {
|
||||
try {
|
||||
child.transferParent(parent);
|
||||
} catch (final RemoteException e) {
|
||||
Log.e(LOGTAG, "Cannot set parent", e);
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(stubName = "GetEditableParent", dispatchTo = "gecko")
|
||||
private static native void nativeGetEditableParent(IGeckoEditableChild child,
|
||||
long contentId, long tabId);
|
||||
|
||||
@Override // IProcessManager
|
||||
public IGeckoEditableParent getEditableParent(final long contentId, final long tabId) {
|
||||
return nativeGetEditableParent(contentId, tabId);
|
||||
public void getEditableParent(final IGeckoEditableChild child,
|
||||
final long contentId, final long tabId) {
|
||||
nativeGetEditableParent(child, contentId, tabId);
|
||||
}
|
||||
|
||||
private static final class ChildConnection implements ServiceConnection,
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.mozilla.gecko.process;
|
|||
|
||||
import org.mozilla.gecko.annotation.WrapForJNI;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.IGeckoEditableChild;
|
||||
import org.mozilla.gecko.IGeckoEditableParent;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
|
@ -28,13 +29,13 @@ public class GeckoServiceChildProcess extends Service {
|
|||
private static IProcessManager sProcessManager;
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static IGeckoEditableParent getEditableParent(final long contentId,
|
||||
final long tabId) {
|
||||
private static void getEditableParent(final IGeckoEditableChild child,
|
||||
final long contentId,
|
||||
final long tabId) {
|
||||
try {
|
||||
return sProcessManager.getEditableParent(contentId, tabId);
|
||||
sProcessManager.getEditableParent(child, contentId, tabId);
|
||||
} catch (final RemoteException e) {
|
||||
Log.e(LOGTAG, "Cannot get editable", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,9 @@ import android.view.inputmethod.EditorInfo;
|
|||
private int mIMEFlags; // Used by IC thread.
|
||||
|
||||
private boolean mIgnoreSelectionChange; // Used by Gecko thread
|
||||
private int mLastTextChangeStart = -1; // Used by Gecko thread
|
||||
private int mLastTextChangeEnd = -1; // Used by Gecko thread
|
||||
private boolean mLastTextChangeReplacedSelection; // Used by Gecko thread
|
||||
|
||||
// Prevent showSoftInput and hideSoftInput from being called multiple times in a row,
|
||||
// including reentrant calls on some devices. Used by UI/IC thread.
|
||||
|
@ -658,10 +661,10 @@ import android.view.inputmethod.EditorInfo;
|
|||
mIcRunHandler = mIcPostHandler = ThreadUtils.getUiHandler();
|
||||
}
|
||||
|
||||
public void setDefaultEditableChild(final IGeckoEditableChild child) {
|
||||
@Override // IGeckoEditableParent
|
||||
public void setDefaultChild(final IGeckoEditableChild child) {
|
||||
if (DEBUG) {
|
||||
// Called by SessionTextInput.
|
||||
ThreadUtils.assertOnUiThread();
|
||||
// On Gecko or binder thread.
|
||||
Log.d(LOGTAG, "setDefaultEditableChild " + child);
|
||||
}
|
||||
mDefaultChild = child;
|
||||
|
@ -1126,6 +1129,45 @@ import android.view.inputmethod.EditorInfo;
|
|||
getConstantName(Action.class, "TYPE_", action.mType) + ")");
|
||||
}
|
||||
switch (action.mType) {
|
||||
case Action.TYPE_REPLACE_TEXT: {
|
||||
final Spanned currentText = mText.getCurrentText();
|
||||
final int actionNewEnd = action.mStart + action.mSequence.length();
|
||||
if (mLastTextChangeStart < 0 || mLastTextChangeEnd > currentText.length() ||
|
||||
action.mStart < mLastTextChangeStart || actionNewEnd > mLastTextChangeEnd) {
|
||||
// Replace-text action doesn't match our text change.
|
||||
break;
|
||||
}
|
||||
|
||||
int indexInText = TextUtils.indexOf(currentText, action.mSequence,
|
||||
action.mStart, mLastTextChangeEnd);
|
||||
if (indexInText < 0 && action.mStart != mLastTextChangeStart) {
|
||||
final String changedText = TextUtils.substring(
|
||||
currentText, mLastTextChangeStart, actionNewEnd);
|
||||
indexInText = changedText.lastIndexOf(action.mSequence.toString());
|
||||
if (indexInText >= 0) {
|
||||
indexInText += mLastTextChangeStart;
|
||||
}
|
||||
}
|
||||
if (indexInText < 0) {
|
||||
// Replace-text action doesn't match our current text.
|
||||
break;
|
||||
}
|
||||
|
||||
// Replace-text action matches our current text; copy the new spans to the
|
||||
// current text.
|
||||
mText.currentReplace(indexInText,
|
||||
indexInText + action.mSequence.length(),
|
||||
action.mSequence);
|
||||
|
||||
// The text change is caused by the replace-text event. If the text change
|
||||
// replaced the previous selection, we need to rely on Gecko for an updated
|
||||
// selection, so don't ignore selection change. However, if the text change
|
||||
// did not replace the previous selection, we can ignore the Gecko selection
|
||||
// in favor of the Java selection.
|
||||
mIgnoreSelectionChange = !mLastTextChangeReplacedSelection;
|
||||
break;
|
||||
}
|
||||
|
||||
case Action.TYPE_SET_SPAN:
|
||||
final int len = mText.getCurrentText().length();
|
||||
if (action.mStart > len || action.mEnd > len ||
|
||||
|
@ -1292,7 +1334,7 @@ import android.view.inputmethod.EditorInfo;
|
|||
}
|
||||
|
||||
@Override // IGeckoEditableParent
|
||||
public void notifyIMEContext(final int state, final String typeHint,
|
||||
public void notifyIMEContext(final IBinder token, final int state, final String typeHint,
|
||||
final String modeHint, final String actionHint,
|
||||
final int flags) {
|
||||
// On Gecko or binder thread.
|
||||
|
@ -1304,9 +1346,14 @@ import android.view.inputmethod.EditorInfo;
|
|||
"\", 0x" + Integer.toHexString(flags) + ")");
|
||||
}
|
||||
|
||||
// Don't check token for notifyIMEContext, because the calls all come
|
||||
// from the parent process.
|
||||
ThreadUtils.assertOnGeckoThread();
|
||||
// Regular notifyIMEContext calls all come from the parent process (with the default child),
|
||||
// so always allow calls from there. We can get additional notifyIMEContext calls during
|
||||
// a session transfer; calls in those cases can come from child processes, and we must
|
||||
// perform a token check in that situation.
|
||||
if (token != mDefaultChild.asBinder() &&
|
||||
!binderCheckToken(token, /* allowNull */ false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIcPostHandler.post(new Runnable() {
|
||||
@Override
|
||||
|
@ -1574,6 +1621,12 @@ import android.view.inputmethod.EditorInfo;
|
|||
mText.currentSetSelection(start, end);
|
||||
}
|
||||
|
||||
// We receive selection change notification after receiving replies for pending
|
||||
// events, so we can reset text change bounds at this point.
|
||||
mLastTextChangeStart = -1;
|
||||
mLastTextChangeEnd = -1;
|
||||
mLastTextChangeReplacedSelection = false;
|
||||
|
||||
mIcPostHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -1605,7 +1658,6 @@ import android.view.inputmethod.EditorInfo;
|
|||
final int currentLength = mText.getCurrentText().length();
|
||||
final int oldEnd = unboundedOldEnd > currentLength ? currentLength : unboundedOldEnd;
|
||||
final int newEnd = start + text.length();
|
||||
final Action action = mActions.peek();
|
||||
|
||||
if (start == 0 && unboundedOldEnd > currentLength) {
|
||||
// | oldEnd > currentLength | signals entire text is cleared (e.g. for
|
||||
|
@ -1617,96 +1669,42 @@ import android.view.inputmethod.EditorInfo;
|
|||
// Don't ignore the next selection change because we are re-syncing with Gecko
|
||||
mIgnoreSelectionChange = false;
|
||||
|
||||
} else if (action != null &&
|
||||
action.mType == Action.TYPE_REPLACE_TEXT &&
|
||||
start <= action.mStart &&
|
||||
oldEnd >= action.mEnd &&
|
||||
newEnd >= action.mStart + action.mSequence.length()) {
|
||||
mLastTextChangeStart = -1;
|
||||
mLastTextChangeEnd = -1;
|
||||
mLastTextChangeReplacedSelection = false;
|
||||
|
||||
// Try to preserve both old spans and new spans in action.mSequence.
|
||||
// indexInText is where we can find waction.mSequence within the passed in text.
|
||||
final int startWithinText = action.mStart - start;
|
||||
int indexInText = TextUtils.indexOf(text, action.mSequence, startWithinText);
|
||||
if (indexInText < 0 && startWithinText >= action.mSequence.length()) {
|
||||
indexInText = text.toString().lastIndexOf(action.mSequence.toString(),
|
||||
startWithinText);
|
||||
}
|
||||
} else if (!geckoIsSameText(start, oldEnd, text)) {
|
||||
final Spanned currentText = mText.getCurrentText();
|
||||
final int selStart = Selection.getSelectionStart(currentText);
|
||||
final int selEnd = Selection.getSelectionEnd(currentText);
|
||||
|
||||
if (indexInText < 0) {
|
||||
// Text was changed from under us. We are forced to discard any new spans.
|
||||
mText.currentReplace(start, oldEnd, text);
|
||||
// True if the selection was in the middle of the replaced text; in that case
|
||||
// we don't know where to place the selection after replacement, and must rely
|
||||
// on the Gecko selection.
|
||||
mLastTextChangeReplacedSelection |=
|
||||
(selStart >= start && selStart <= oldEnd) ||
|
||||
(selEnd >= start && selEnd <= oldEnd);
|
||||
|
||||
// Don't ignore the next selection change because we are forced to re-sync
|
||||
// with Gecko here.
|
||||
mIgnoreSelectionChange = false;
|
||||
|
||||
} else if (indexInText == 0 && text.length() == action.mSequence.length() &&
|
||||
oldEnd - start == action.mEnd - action.mStart) {
|
||||
// The new change exactly matches our saved change, so do a direct replace.
|
||||
mText.currentReplace(start, oldEnd, action.mSequence);
|
||||
|
||||
// Ignore the next selection change because the selection change is a
|
||||
// side-effect of the replace-text event we sent.
|
||||
mIgnoreSelectionChange = true;
|
||||
|
||||
} else {
|
||||
// The sequence is embedded within the changed text, so we have to perform
|
||||
// replacement in parts. First replace part of text before the sequence.
|
||||
mText.currentReplace(start, action.mStart, text.subSequence(0, indexInText));
|
||||
|
||||
// Then replace part of the text after the sequence.
|
||||
final int actionStart = indexInText + start;
|
||||
final int delta = actionStart - action.mStart;
|
||||
final int actionEnd = delta + action.mEnd;
|
||||
|
||||
final Spanned currentText = mText.getCurrentText();
|
||||
final boolean resetSelStart = Selection.getSelectionStart(currentText) == actionEnd;
|
||||
final boolean resetSelEnd = Selection.getSelectionEnd(currentText) == actionEnd;
|
||||
|
||||
mText.currentReplace(actionEnd, delta + oldEnd, text.subSequence(
|
||||
indexInText + action.mSequence.length(), text.length()));
|
||||
|
||||
// The replacement above may have shifted our selection, if the selection
|
||||
// was at the start of the replacement range. If so, we need to reset
|
||||
// our selection to the previous position.
|
||||
if (resetSelStart || resetSelEnd) {
|
||||
mText.currentSetSelection(
|
||||
resetSelStart ? actionEnd : Selection.getSelectionStart(currentText),
|
||||
resetSelEnd ? actionEnd : Selection.getSelectionEnd(currentText));
|
||||
}
|
||||
|
||||
// Finally replace the sequence itself to preserve new spans.
|
||||
mText.currentReplace(actionStart, actionEnd, action.mSequence);
|
||||
|
||||
// If one of the Java selection ends is not at the end of the replaced
|
||||
// text, we want to preserve that selection, so we ignore the Gecko
|
||||
// selection change notification. On the other hand, if the Java selection
|
||||
// is normal, we want to try syncing the Java selection to the Gecko
|
||||
// selection, because this text change could have changed the Gecko
|
||||
// selection to elsewhere; so in that case, don't ignore the Gecko
|
||||
// selection change notification.
|
||||
mIgnoreSelectionChange = !resetSelStart || !resetSelEnd;
|
||||
}
|
||||
|
||||
} else if (geckoIsSameText(start, oldEnd, text)) {
|
||||
// Nothing to do because the text is the same. This could happen when
|
||||
// the composition is updated for example, in which case we want to keep the
|
||||
// Java selection.
|
||||
mIgnoreSelectionChange = mIgnoreSelectionChange || (action != null &&
|
||||
(action.mType == Action.TYPE_REPLACE_TEXT ||
|
||||
action.mType == Action.TYPE_SET_SPAN ||
|
||||
action.mType == Action.TYPE_REMOVE_SPAN));
|
||||
return;
|
||||
|
||||
} else {
|
||||
// Gecko side initiated the text change. Replace in two steps to properly
|
||||
// clear composing spans that span the whole range.
|
||||
mText.currentReplace(start, oldEnd, "");
|
||||
mText.currentReplace(start, start, text);
|
||||
|
||||
// Don't ignore the next selection change because we are forced to re-sync
|
||||
// with Gecko here.
|
||||
mIgnoreSelectionChange = false;
|
||||
mLastTextChangeStart = start;
|
||||
mLastTextChangeEnd = newEnd;
|
||||
|
||||
} else {
|
||||
// Nothing to do because the text is the same. This could happen when
|
||||
// the composition is updated for example, in which case we want to keep the
|
||||
// Java selection.
|
||||
final Action action = mActions.peek();
|
||||
mIgnoreSelectionChange = mIgnoreSelectionChange || (action != null &&
|
||||
(action.mType == Action.TYPE_REPLACE_TEXT ||
|
||||
action.mType == Action.TYPE_SET_SPAN ||
|
||||
action.mType == Action.TYPE_REMOVE_SPAN));
|
||||
|
||||
mLastTextChangeStart = start;
|
||||
mLastTextChangeEnd = newEnd;
|
||||
}
|
||||
|
||||
// onTextChange is always followed by onSelectionChange, so we let
|
||||
|
@ -1785,7 +1783,7 @@ import android.view.inputmethod.EditorInfo;
|
|||
} else if (chr == '\n') {
|
||||
return "\u21b2";
|
||||
}
|
||||
return String.format("%04x", (int) chr);
|
||||
return String.format("\\u%04x", (int) chr);
|
||||
}
|
||||
|
||||
static StringBuilder debugAppend(StringBuilder sb, Object obj) {
|
||||
|
|
|
@ -730,8 +730,7 @@ public class GeckoSession extends LayerSession
|
|||
GeckoBundle initData);
|
||||
|
||||
@WrapForJNI(dispatchTo = "proxy")
|
||||
public native void attachEditable(IGeckoEditableParent parent,
|
||||
GeckoEditableChild child);
|
||||
public native void attachEditable(IGeckoEditableParent parent);
|
||||
|
||||
@WrapForJNI(dispatchTo = "proxy")
|
||||
public native void attachAccessibility(SessionAccessibility.NativeProvider sessionAccessibility);
|
||||
|
|
|
@ -275,7 +275,6 @@ public final class SessionTextInput {
|
|||
private final GeckoSession mSession;
|
||||
private final NativeQueue mQueue;
|
||||
private final GeckoEditable mEditable;
|
||||
private final GeckoEditableChild mEditableChild;
|
||||
private InputConnectionClient mInputConnection;
|
||||
private GeckoSession.TextInputDelegate mDelegate;
|
||||
// Auto-fill nodes.
|
||||
|
@ -289,8 +288,6 @@ public final class SessionTextInput {
|
|||
mSession = session;
|
||||
mQueue = queue;
|
||||
mEditable = new GeckoEditable(session);
|
||||
mEditableChild = new GeckoEditableChild(mEditable);
|
||||
mEditable.setDefaultEditableChild(mEditableChild);
|
||||
|
||||
session.getEventDispatcher().registerUiThreadListener(
|
||||
new BundleEventListener() {
|
||||
|
@ -314,11 +311,10 @@ public final class SessionTextInput {
|
|||
|
||||
/* package */ void onWindowChanged(final GeckoSession.Window window) {
|
||||
if (mQueue.isReady()) {
|
||||
window.attachEditable(mEditable, mEditableChild);
|
||||
window.attachEditable(mEditable);
|
||||
} else {
|
||||
mQueue.queueUntilReady(window, "attachEditable",
|
||||
IGeckoEditableParent.class, mEditable,
|
||||
GeckoEditableChild.class, mEditableChild);
|
||||
IGeckoEditableParent.class, mEditable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -372,6 +372,17 @@ public class testInputConnection extends JavascriptBridgeTest {
|
|||
ic.deleteSurroundingText(1, 0);
|
||||
assertTextAndSelectionAt("Can clear text", ic, "", 0);
|
||||
|
||||
// Bug 1490391 - Committing then setting composition can result in duplicates.
|
||||
ic.commitText("far", 1);
|
||||
ic.setComposingText("bar", 1);
|
||||
assertTextAndSelectionAt("Can commit then set composition", ic, "farbar", 6);
|
||||
ic.setComposingText("baz", 1);
|
||||
assertTextAndSelectionAt("Composition still exists after setting", ic, "farbaz", 6);
|
||||
|
||||
ic.finishComposingText();
|
||||
ic.deleteSurroundingText(6, 0);
|
||||
assertTextAndSelectionAt("Can clear text", ic, "", 0);
|
||||
|
||||
// Make sure we don't leave behind stale events for the following test.
|
||||
processGeckoEvents();
|
||||
processInputConnectionEvents();
|
||||
|
|
|
@ -29,7 +29,7 @@ web-platform-tests:
|
|||
linux.*/debug: 18
|
||||
macosx64.*/opt: 8
|
||||
macosx64/debug: 16
|
||||
windows10-64-ccov/debug: 15
|
||||
windows10.*/debug: 18
|
||||
macosx64-ccov/debug: 24
|
||||
default: 12
|
||||
max-run-time:
|
||||
|
|
|
@ -1,32 +1,4 @@
|
|||
[request-consume-empty.html]
|
||||
max-asserts: 2
|
||||
[Consume request's body as text]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as blob]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as arrayBuffer]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as json]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as formData]
|
||||
expected: FAIL
|
||||
|
||||
[Consume empty FormData request body as text]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as json (error case)]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as formData with correct multipart type (error case)]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as formData with correct urlencoded type]
|
||||
expected: FAIL
|
||||
|
||||
[Consume request's body as formData without correct type (error case)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
[request-disturbed.html]
|
||||
[Request without body cannot be disturbed]
|
||||
expected: FAIL
|
||||
|
||||
[Request's body: initial state]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,32 +1,3 @@
|
|||
[response-consume-empty.html]
|
||||
max-asserts: 2
|
||||
[Consume response's body as text]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as blob]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as arrayBuffer]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as json]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as formData]
|
||||
expected: FAIL
|
||||
|
||||
[Consume empty FormData response body as text]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as json (error case)]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as formData with correct multipart type (error case)]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as formData with correct urlencoded type]
|
||||
expected: FAIL
|
||||
|
||||
[Consume response's body as formData without correct type (error case)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
[area-coords.html]
|
||||
max-asserts: 102
|
||||
|
||||
[COMMA: "2,2,10,10" (rect)]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
[cache-add.https.html]
|
||||
[Cache.add with request with null body (not consumed)]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[cache-add.https.html]
|
||||
[Cache.add with request with null body (not consumed)]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[cache-add.https.html]
|
||||
[Cache.add with request with null body (not consumed)]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[same-origin.html]
|
||||
[unsupported_scheme]
|
||||
expected: FAIL
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[same-origin.html]
|
||||
[unsupported_scheme]
|
||||
expected: FAIL
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/TextComposition.h"
|
||||
#include "mozilla/TextEventDispatcherListener.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
|
||||
#include <android/api-level.h>
|
||||
#include <android/input.h>
|
||||
|
@ -585,18 +586,19 @@ GeckoEditableSupport::GetComposition() const
|
|||
return widget ? IMEStateManager::GetTextCompositionFor(widget) : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
GeckoEditableSupport::RemoveComposition(RemoveCompositionFlag aFlag)
|
||||
{
|
||||
if (!mDispatcher || !mDispatcher->IsComposing()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
||||
NS_ENSURE_SUCCESS_VOID(BeginInputTransaction(mDispatcher));
|
||||
NS_ENSURE_SUCCESS(BeginInputTransaction(mDispatcher), false);
|
||||
mDispatcher->CommitComposition(
|
||||
status, aFlag == CANCEL_IME_COMPOSITION ? &EmptyString() : nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -903,16 +905,18 @@ GeckoEditableSupport::FlushIMEChanges(FlushChangesFlag aFlags)
|
|||
}
|
||||
}
|
||||
|
||||
while (mIMEDelaySynchronizeReply && mIMEActiveSynchronizeCount) {
|
||||
mIMEActiveSynchronizeCount--;
|
||||
mEditable->NotifyIME(EditableListener::NOTIFY_IME_REPLY_EVENT);
|
||||
}
|
||||
mIMEDelaySynchronizeReply = false;
|
||||
mIMEActiveSynchronizeCount = 0;
|
||||
|
||||
if (mIMESelectionChanged) {
|
||||
mIMESelectionChanged = false;
|
||||
mEditable->OnSelectionChange(selStart, selEnd);
|
||||
flushOnException();
|
||||
}
|
||||
|
||||
while (mIMEActiveReplaceTextCount) {
|
||||
mIMEActiveReplaceTextCount--;
|
||||
OnImeSynchronize();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -961,6 +965,12 @@ GeckoEditableSupport::UpdateCompositionRects()
|
|||
void
|
||||
GeckoEditableSupport::OnImeSynchronize()
|
||||
{
|
||||
if (mIMEDelaySynchronizeReply) {
|
||||
// If we are waiting for other events to reply,
|
||||
// queue this reply as well.
|
||||
mIMEActiveSynchronizeCount++;
|
||||
return;
|
||||
}
|
||||
if (!mIMEMaskEventsCount) {
|
||||
FlushIMEChanges();
|
||||
}
|
||||
|
@ -971,13 +981,11 @@ void
|
|||
GeckoEditableSupport::OnImeReplaceText(int32_t aStart, int32_t aEnd,
|
||||
jni::String::Param aText)
|
||||
{
|
||||
mIMEActiveReplaceTextCount++;
|
||||
|
||||
if (!DoReplaceText(aStart, aEnd, aText)) {
|
||||
// We did not process the event, so reply to it now.
|
||||
mIMEActiveReplaceTextCount--;
|
||||
OnImeSynchronize();
|
||||
if (DoReplaceText(aStart, aEnd, aText)) {
|
||||
mIMEDelaySynchronizeReply = true;
|
||||
}
|
||||
|
||||
OnImeSynchronize();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -1010,6 +1018,7 @@ GeckoEditableSupport::DoReplaceText(int32_t aStart, int32_t aEnd,
|
|||
nsString string(aText->ToString());
|
||||
const bool composing = !mIMERanges->IsEmpty();
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
bool textChanged = composing;
|
||||
|
||||
if (!mIMEKeyEvents.IsEmpty() ||
|
||||
!composition || !mDispatcher->IsComposing() ||
|
||||
|
@ -1019,7 +1028,7 @@ GeckoEditableSupport::DoReplaceText(int32_t aStart, int32_t aEnd,
|
|||
// Only start a new composition if we have key events,
|
||||
// if we don't have an existing composition, or
|
||||
// the replaced text does not match our composition.
|
||||
RemoveComposition();
|
||||
textChanged |= RemoveComposition();
|
||||
|
||||
{
|
||||
// Use text selection to set target position(s) for
|
||||
|
@ -1061,6 +1070,7 @@ GeckoEditableSupport::DoReplaceText(int32_t aStart, int32_t aEnd,
|
|||
if (!mDispatcher || widget->Destroyed()) {
|
||||
return false;
|
||||
}
|
||||
textChanged = true;
|
||||
}
|
||||
} else if (composition->String().Equals(string)) {
|
||||
/* If the new text is the same as the existing composition text,
|
||||
|
@ -1070,7 +1080,10 @@ GeckoEditableSupport::DoReplaceText(int32_t aStart, int32_t aEnd,
|
|||
IMETextChange dummyChange;
|
||||
dummyChange.mStart = aStart;
|
||||
dummyChange.mOldEnd = dummyChange.mNewEnd = aEnd;
|
||||
PostFlushIMEChanges();
|
||||
mIMESelectionChanged = true;
|
||||
AddIMETextChange(dummyChange);
|
||||
textChanged = true;
|
||||
}
|
||||
|
||||
if (sDispatchKeyEventsInCompositionForAnyApps ||
|
||||
|
@ -1088,6 +1101,7 @@ GeckoEditableSupport::DoReplaceText(int32_t aStart, int32_t aEnd,
|
|||
mIMERanges->Clear();
|
||||
} else if (!string.IsEmpty() || mDispatcher->IsComposing()) {
|
||||
mDispatcher->CommitComposition(status, &string);
|
||||
textChanged = true;
|
||||
}
|
||||
if (!mDispatcher || widget->Destroyed()) {
|
||||
return false;
|
||||
|
@ -1098,7 +1112,7 @@ GeckoEditableSupport::DoReplaceText(int32_t aStart, int32_t aEnd,
|
|||
SendIMEDummyKeyEvent(widget, eKeyUp);
|
||||
// Widget may be destroyed after dispatching the above event.
|
||||
}
|
||||
return true;
|
||||
return textChanged;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1131,28 +1145,38 @@ GeckoEditableSupport::OnImeAddCompositionRange(
|
|||
void
|
||||
GeckoEditableSupport::OnImeUpdateComposition(int32_t aStart, int32_t aEnd,
|
||||
int32_t aFlags)
|
||||
{
|
||||
if (DoUpdateComposition(aStart, aEnd, aFlags)) {
|
||||
mIMEDelaySynchronizeReply = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GeckoEditableSupport::DoUpdateComposition(int32_t aStart, int32_t aEnd,
|
||||
int32_t aFlags)
|
||||
{
|
||||
if (mIMEMaskEventsCount > 0) {
|
||||
// Not focused.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
NS_ENSURE_TRUE_VOID(mDispatcher && widget);
|
||||
NS_ENSURE_TRUE(mDispatcher && widget, false);
|
||||
|
||||
const bool keepCurrent = !!(aFlags &
|
||||
java::GeckoEditableChild::FLAG_KEEP_CURRENT_COMPOSITION);
|
||||
bool compositionChanged = false;
|
||||
|
||||
// A composition with no ranges means we want to set the selection.
|
||||
if (mIMERanges->IsEmpty()) {
|
||||
if (keepCurrent && mDispatcher->IsComposing()) {
|
||||
// Don't set selection if we want to keep current composition.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aStart >= 0 && aEnd >= 0);
|
||||
RemoveComposition();
|
||||
compositionChanged = RemoveComposition();
|
||||
|
||||
WidgetSelectionEvent selEvent(true, eSetSelection, widget);
|
||||
selEvent.mOffset = std::min(aStart, aEnd);
|
||||
|
@ -1160,7 +1184,7 @@ GeckoEditableSupport::OnImeUpdateComposition(int32_t aStart, int32_t aEnd,
|
|||
selEvent.mReversed = aStart > aEnd;
|
||||
selEvent.mExpandToClusterBoundary = false;
|
||||
widget->DispatchEvent(&selEvent, status);
|
||||
return;
|
||||
return compositionChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1181,12 +1205,13 @@ GeckoEditableSupport::OnImeUpdateComposition(int32_t aStart, int32_t aEnd,
|
|||
if (keepCurrent) {
|
||||
// Don't start a new composition if we want to keep the current one.
|
||||
mIMERanges->Clear();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only start new composition if we don't have an existing one,
|
||||
// or if the existing composition doesn't match the new one.
|
||||
RemoveComposition();
|
||||
compositionChanged = true;
|
||||
|
||||
{
|
||||
WidgetSelectionEvent event(true, eSetSelection, widget);
|
||||
|
@ -1218,11 +1243,12 @@ GeckoEditableSupport::OnImeUpdateComposition(int32_t aStart, int32_t aEnd,
|
|||
|
||||
if (NS_WARN_IF(NS_FAILED(BeginInputTransaction(mDispatcher)))) {
|
||||
mIMERanges->Clear();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
mDispatcher->SetPendingComposition(string, mIMERanges);
|
||||
mDispatcher->FlushPendingComposition(status);
|
||||
mIMERanges->Clear();
|
||||
return compositionChanged;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1330,7 +1356,8 @@ GeckoEditableSupport::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
|||
RefPtr<GeckoEditableSupport> self(this);
|
||||
nsAppShell::PostEvent([this, self] {
|
||||
if (!mIMEFocusCount) {
|
||||
mIMEActiveReplaceTextCount = 0;
|
||||
mIMEDelaySynchronizeReply = false;
|
||||
mIMEActiveSynchronizeCount = 0;
|
||||
mEditable->NotifyIME(EditableListener::NOTIFY_IME_OF_BLUR);
|
||||
OnRemovedFrom(mDispatcher);
|
||||
}
|
||||
|
@ -1383,7 +1410,7 @@ GeckoEditableSupport::OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher)
|
|||
{
|
||||
mDispatcher = nullptr;
|
||||
|
||||
if (mIsRemote) {
|
||||
if (mIsRemote && mEditable->HasEditableParent()) {
|
||||
// When we're remote, detach every time.
|
||||
OnDetach(NS_NewRunnableFunction("GeckoEditableSupport::OnRemovedFrom",
|
||||
[editable = java::GeckoEditableChild::GlobalRef(mEditable)] {
|
||||
|
@ -1425,27 +1452,34 @@ GeckoEditableSupport::SetInputContext(const InputContext& aContext,
|
|||
return;
|
||||
}
|
||||
|
||||
const bool inPrivateBrowsing = mInputContext.mInPrivateBrowsing;
|
||||
// Post an event to keep calls in order relative to NotifyIME.
|
||||
nsAppShell::PostEvent([this, self = RefPtr<GeckoEditableSupport>(this),
|
||||
context = mInputContext, action = aAction] {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
|
||||
if (!widget || widget->Destroyed()) {
|
||||
return;
|
||||
}
|
||||
NotifyIMEContext(context, action);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
GeckoEditableSupport::NotifyIMEContext(const InputContext& aContext,
|
||||
const InputContextAction& aAction)
|
||||
{
|
||||
const bool inPrivateBrowsing = aContext.mInPrivateBrowsing;
|
||||
const bool isUserAction =
|
||||
aAction.IsHandlingUserInput() || aContext.mHasHandledUserInput;
|
||||
const int32_t flags =
|
||||
(inPrivateBrowsing ? EditableListener::IME_FLAG_PRIVATE_BROWSING : 0) |
|
||||
(isUserAction ? EditableListener::IME_FLAG_USER_ACTION : 0);
|
||||
|
||||
// Post an event to keep calls in order relative to NotifyIME.
|
||||
nsAppShell::PostEvent([this, self = RefPtr<GeckoEditableSupport>(this),
|
||||
flags, context = mInputContext] {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
|
||||
if (!widget || widget->Destroyed()) {
|
||||
return;
|
||||
}
|
||||
mEditable->NotifyIMEContext(context.mIMEState.mEnabled,
|
||||
context.mHTMLInputType,
|
||||
context.mHTMLInputInputmode,
|
||||
context.mActionHint,
|
||||
flags);
|
||||
});
|
||||
mEditable->NotifyIMEContext(aContext.mIMEState.mEnabled,
|
||||
aContext.mHTMLInputType,
|
||||
aContext.mHTMLInputInputmode,
|
||||
aContext.mActionHint,
|
||||
flags);
|
||||
}
|
||||
|
||||
InputContext
|
||||
|
@ -1456,5 +1490,89 @@ GeckoEditableSupport::GetInputContext()
|
|||
return context;
|
||||
}
|
||||
|
||||
void
|
||||
GeckoEditableSupport::TransferParent(jni::Object::Param aEditableParent)
|
||||
{
|
||||
mEditable->SetParent(aEditableParent);
|
||||
|
||||
// If we are already focused, make sure the new parent has our token
|
||||
// and focus information, so it can accept additional calls from us.
|
||||
if (mIMEFocusCount > 0) {
|
||||
mEditable->NotifyIME(EditableListener::NOTIFY_IME_OF_TOKEN);
|
||||
NotifyIMEContext(mInputContext, InputContextAction());
|
||||
mEditable->NotifyIME(EditableListener::NOTIFY_IME_OF_FOCUS);
|
||||
}
|
||||
|
||||
if (mIsRemote && !mDispatcher) {
|
||||
// Detach now if we were only attached temporarily.
|
||||
OnRemovedFrom(/* dispatcher */ nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GeckoEditableSupport::SetOnTabChild(dom::TabChild* aTabChild)
|
||||
{
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
NS_ENSURE_TRUE_VOID(aTabChild);
|
||||
|
||||
const dom::ContentChild* const contentChild =
|
||||
dom::ContentChild::GetSingleton();
|
||||
RefPtr<widget::PuppetWidget> widget(aTabChild->WebWidget());
|
||||
NS_ENSURE_TRUE_VOID(contentChild && widget);
|
||||
|
||||
// Get the content/tab ID in order to get the correct
|
||||
// IGeckoEditableParent object, which GeckoEditableChild uses to
|
||||
// communicate with the parent process.
|
||||
const uint64_t contentId = contentChild->GetID();
|
||||
const uint64_t tabId = aTabChild->GetTabId();
|
||||
NS_ENSURE_TRUE_VOID(contentId && tabId);
|
||||
|
||||
RefPtr<widget::TextEventDispatcherListener> listener =
|
||||
widget->GetNativeTextEventDispatcherListener();
|
||||
|
||||
if (!listener || listener.get() ==
|
||||
static_cast<widget::TextEventDispatcherListener*>(widget)) {
|
||||
// We need to set a new listener.
|
||||
const auto editableChild = java::GeckoEditableChild::New(
|
||||
/* parent */ nullptr, /* default */ false);
|
||||
RefPtr<widget::GeckoEditableSupport> editableSupport =
|
||||
new widget::GeckoEditableSupport(editableChild);
|
||||
|
||||
// Tell PuppetWidget to use our listener for IME operations.
|
||||
widget->SetNativeTextEventDispatcherListener(editableSupport);
|
||||
|
||||
// Temporarily attach so we can receive the initial editable parent.
|
||||
AttachNative(editableChild, editableSupport);
|
||||
editableSupport->mEditableAttached = true;
|
||||
|
||||
// Connect the new child to a parent that corresponds to the TabChild.
|
||||
java::GeckoServiceChildProcess::GetEditableParent(
|
||||
editableChild, contentId, tabId);
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to update the existing listener to use the new parent.
|
||||
|
||||
// We expect the existing TextEventDispatcherListener to be a
|
||||
// GeckoEditableSupport object, so we perform a sanity check to make
|
||||
// sure, by comparing their respective vtable pointers.
|
||||
const RefPtr<widget::GeckoEditableSupport> dummy =
|
||||
new widget::GeckoEditableSupport(/* child */ nullptr);
|
||||
NS_ENSURE_TRUE_VOID(*reinterpret_cast<const uintptr_t*>(listener.get()) ==
|
||||
*reinterpret_cast<const uintptr_t*>(dummy.get()));
|
||||
|
||||
const auto support =
|
||||
static_cast<widget::GeckoEditableSupport*>(listener.get());
|
||||
if (!support->mEditableAttached) {
|
||||
// Temporarily attach so we can receive the initial editable parent.
|
||||
AttachNative(support->GetJavaEditable(), support);
|
||||
support->mEditableAttached = true;
|
||||
}
|
||||
|
||||
// Transfer to a new parent that corresponds to the TabChild.
|
||||
java::GeckoServiceChildProcess::GetEditableParent(
|
||||
support->GetJavaEditable(), contentId, tabId);
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -21,6 +21,10 @@ namespace mozilla {
|
|||
|
||||
class TextComposition;
|
||||
|
||||
namespace dom {
|
||||
class TabChild;
|
||||
}
|
||||
|
||||
namespace widget {
|
||||
|
||||
class GeckoEditableSupport final
|
||||
|
@ -92,7 +96,8 @@ class GeckoEditableSupport final
|
|||
RefPtr<TextRangeArray> mIMERanges;
|
||||
int32_t mIMEMaskEventsCount; // Mask events when > 0.
|
||||
int32_t mIMEFocusCount; // We are focused when > 0.
|
||||
int32_t mIMEActiveReplaceTextCount; // We still need to reply when > 0.
|
||||
bool mIMEDelaySynchronizeReply; // We reply asynchronously when true.
|
||||
int32_t mIMEActiveSynchronizeCount; // The number of replies being delayed.
|
||||
bool mIMESelectionChanged;
|
||||
bool mIMETextChangedDuringFlush;
|
||||
bool mIMEMonitorCursor;
|
||||
|
@ -118,7 +123,7 @@ class GeckoEditableSupport final
|
|||
virtual ~GeckoEditableSupport() {}
|
||||
|
||||
RefPtr<TextComposition> GetComposition() const;
|
||||
void RemoveComposition(
|
||||
bool RemoveComposition(
|
||||
RemoveCompositionFlag aFlag = COMMIT_IME_COMPOSITION);
|
||||
void SendIMEDummyKeyEvent(nsIWidget* aWidget, EventMessage msg);
|
||||
void AddIMETextChange(const IMETextChange& aChange);
|
||||
|
@ -128,6 +133,9 @@ class GeckoEditableSupport final
|
|||
void AsyncNotifyIME(int32_t aNotification);
|
||||
void UpdateCompositionRects();
|
||||
bool DoReplaceText(int32_t aStart, int32_t aEnd, jni::String::Param aText);
|
||||
bool DoUpdateComposition(int32_t aStart, int32_t aEnd, int32_t aFlags);
|
||||
void NotifyIMEContext(const InputContext& aContext,
|
||||
const InputContextAction& aAction);
|
||||
|
||||
public:
|
||||
template<typename Functor>
|
||||
|
@ -162,6 +170,8 @@ public:
|
|||
std::move(aCall)));
|
||||
}
|
||||
|
||||
static void SetOnTabChild(dom::TabChild* aTabChild);
|
||||
|
||||
// Constructor for main process GeckoEditableChild.
|
||||
GeckoEditableSupport(nsWindow::NativePtr<GeckoEditableSupport>* aPtr,
|
||||
nsWindow* aWindow,
|
||||
|
@ -173,7 +183,8 @@ public:
|
|||
, mIMERanges(new TextRangeArray())
|
||||
, mIMEMaskEventsCount(1) // Mask IME events since there's no focus yet
|
||||
, mIMEFocusCount(0)
|
||||
, mIMEActiveReplaceTextCount(0)
|
||||
, mIMEDelaySynchronizeReply(false)
|
||||
, mIMEActiveSynchronizeCount(0)
|
||||
, mIMESelectionChanged(false)
|
||||
, mIMETextChangedDuringFlush(false)
|
||||
, mIMEMonitorCursor(false)
|
||||
|
@ -225,6 +236,9 @@ public:
|
|||
});
|
||||
}
|
||||
|
||||
// Transfer to a new parent.
|
||||
void TransferParent(jni::Object::Param aEditableParent);
|
||||
|
||||
// Handle an Android KeyEvent.
|
||||
void OnKeyEvent(int32_t aAction, int32_t aKeyCode, int32_t aScanCode,
|
||||
int32_t aMetaState, int32_t aKeyPressMetaState,
|
||||
|
|
|
@ -42,18 +42,16 @@ class GeckoProcessManager final
|
|||
}
|
||||
|
||||
public:
|
||||
static jni::Object::LocalRef
|
||||
GetEditableParent(int64_t aContentId, int64_t aTabId)
|
||||
static void
|
||||
GetEditableParent(jni::Object::Param aEditableChild,
|
||||
int64_t aContentId, int64_t aTabId)
|
||||
{
|
||||
// On binder thread.
|
||||
jni::Object::GlobalRef ret;
|
||||
nsAppShell::SyncRunEvent([aContentId, aTabId, &ret] {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget(aContentId, aTabId);
|
||||
if (widget) {
|
||||
ret = static_cast<nsWindow*>(widget.get())->GetEditableParent();
|
||||
}
|
||||
});
|
||||
return ret;
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget(aContentId, aTabId);
|
||||
if (widget && widget->GetNativeData(NS_NATIVE_WIDGET) == widget) {
|
||||
java::GeckoProcessManager::SetEditableChildParent(
|
||||
aEditableChild,
|
||||
static_cast<nsWindow*>(widget.get())->GetEditableParent());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "nsIDOMWakeLockListener.h"
|
||||
#include "nsIPowerManagerService.h"
|
||||
#include "nsISpeculativeConnect.h"
|
||||
#include "nsITabChild.h"
|
||||
#include "nsIURIFixup.h"
|
||||
#include "nsCategoryManagerUtils.h"
|
||||
#include "nsCDefaultURIFixup.h"
|
||||
|
@ -553,6 +552,7 @@ nsAppShell::Init()
|
|||
obsServ->AddObserver(this, "chrome-document-loaded", false);
|
||||
} else {
|
||||
obsServ->AddObserver(this, "content-document-global-created", false);
|
||||
obsServ->AddObserver(this, "geckoview-content-global-transferred", false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -678,38 +678,15 @@ nsAppShell::Observe(nsISupports* aSubject,
|
|||
nsPIDOMWindowOuter::From(domWindow));
|
||||
NS_ENSURE_TRUE(domWidget, NS_OK);
|
||||
|
||||
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
|
||||
dom::TabChild* tabChild = domWidget->GetOwningTabChild();
|
||||
RefPtr<widget::PuppetWidget> widget(tabChild->WebWidget());
|
||||
NS_ENSURE_TRUE(contentChild && tabChild && widget, NS_OK);
|
||||
widget::GeckoEditableSupport::SetOnTabChild(
|
||||
domWidget->GetOwningTabChild());
|
||||
|
||||
widget::TextEventDispatcherListener* listener =
|
||||
widget->GetNativeTextEventDispatcherListener();
|
||||
if (listener && listener !=
|
||||
static_cast<widget::TextEventDispatcherListener*>(widget)) {
|
||||
// We already set a listener before.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Get the content/tab ID in order to get the correct
|
||||
// IGeckoEditableParent object, which GeckoEditableChild uses to
|
||||
// communicate with the parent process.
|
||||
const uint64_t contentId = contentChild->GetID();
|
||||
const uint64_t tabId = tabChild->GetTabId();
|
||||
NS_ENSURE_TRUE(contentId && tabId, NS_OK);
|
||||
|
||||
auto editableParent = java::GeckoServiceChildProcess::GetEditableParent(
|
||||
contentId, tabId);
|
||||
NS_ENSURE_TRUE(editableParent, NS_OK);
|
||||
|
||||
auto editableChild = java::GeckoEditableChild::New(editableParent);
|
||||
NS_ENSURE_TRUE(editableChild, NS_OK);
|
||||
|
||||
RefPtr<widget::GeckoEditableSupport> editableSupport =
|
||||
new widget::GeckoEditableSupport(editableChild);
|
||||
|
||||
// Tell PuppetWidget to use our listener for IME operations.
|
||||
widget->SetNativeTextEventDispatcherListener(editableSupport);
|
||||
} else if (!strcmp(aTopic, "geckoview-content-global-transferred")) {
|
||||
// We're transferring to a new GeckoEditableParent, so notify the
|
||||
// existing GeckoEditableChild instance associated with the docshell.
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aSubject);
|
||||
widget::GeckoEditableSupport::SetOnTabChild(
|
||||
dom::TabChild::GetFrom(docShell));
|
||||
}
|
||||
|
||||
if (removeObserver) {
|
||||
|
|
|
@ -361,8 +361,7 @@ public:
|
|||
jni::Object::Param aInitData);
|
||||
|
||||
void AttachEditable(const GeckoSession::Window::LocalRef& inst,
|
||||
jni::Object::Param aEditableParent,
|
||||
jni::Object::Param aEditableChild);
|
||||
jni::Object::Param aEditableParent);
|
||||
|
||||
void AttachAccessibility(const GeckoSession::Window::LocalRef& inst,
|
||||
jni::Object::Param aSessionAccessibility);
|
||||
|
@ -1362,18 +1361,16 @@ nsWindow::GeckoViewSupport::Transfer(const GeckoSession::Window::LocalRef& inst,
|
|||
|
||||
void
|
||||
nsWindow::GeckoViewSupport::AttachEditable(const GeckoSession::Window::LocalRef& inst,
|
||||
jni::Object::Param aEditableParent,
|
||||
jni::Object::Param aEditableChild)
|
||||
jni::Object::Param aEditableParent)
|
||||
{
|
||||
java::GeckoEditableChild::LocalRef editableChild(inst.Env());
|
||||
editableChild = java::GeckoEditableChild::Ref::From(aEditableChild);
|
||||
|
||||
if (window.mEditableSupport) {
|
||||
window.mEditableSupport.Detach(
|
||||
window.mEditableSupport->GetJavaEditable());
|
||||
if (!window.mEditableSupport) {
|
||||
auto editableChild = java::GeckoEditableChild::New(aEditableParent,
|
||||
/* default */ true);
|
||||
window.mEditableSupport.Attach(editableChild, &window, editableChild);
|
||||
} else {
|
||||
window.mEditableSupport->TransferParent(aEditableParent);
|
||||
}
|
||||
|
||||
window.mEditableSupport.Attach(editableChild, &window, editableChild);
|
||||
window.mEditableParent = aEditableParent;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче