mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 13:23:07 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- bug 1215748 - use llvm-dsymutil for mac builds. r=mshal (a217006d89) - warnings (31ea43d0d8) - Bug 1175154 - Unit tests for IAC on 3.0. r=ferjm (12c424bab3) - Bug 1219543 - Part 1: isRunningOnCompositor flag is now a member of AnimationProperty. r=bbirtles (85bc668501) - Bug 1219543 - Part 2: Avoid the period that mIsRunningOnCompositor is false between restyling and building display list. r=bbirtles (597e46d479) - Bug 1219543 - Part 3: MutationObserver should disconnect when the test is finished. r=bbirtles (70c26a266e) - Bug 1214148 - patch 1 - propagation from the nested iframe back to the toplevel iframe, r=alwu (b42002f43a) - Bug 1214148 - patch 2 - from toplevel iframe to the nested iframe, r=alwu (7b07fe5399) - Bug 1214148 - patch 3 - correct window for nested iframes, r=alwu (27ee08caf1) - Bug 1166910 - put referrer attribute behind pref in webidl, r=bz (93e421fa1b) - Bug 1187357 - rename referrer attribute to referrerpolicy. r=hsivonen (70c67f5def) - Bug 1187357 - Generated code for renaming referrer to referrerpolicy in html parser. r=hsivonen (738de3f278) - Bug 1221341. Snap box shadow clip rect to device pixels. r=mstange (b63b783714) - Bug 1228634 - Implement Element.getAttributeNames, r=peterv (4594d9c14c) - Bug 1216193. Implement webkitMatchesSelector. r=khuey (39742b7e0b) - Bug 1134648, handle dynamic changes to rel=dns-prefetch, r=bz (e27638080e) - Bug 1229962 - use UniquePtr<T[]> instead of nsAutoArrayPtr<T> in parser/html/; r=hsivonen (75de6314f1) - Bug 1226437 - Speculative CSP should set speculative referrer policy instead of actual referrer policy. r=sicking (f7dfd3fd18) - Bug 1227554 - Default to NullPrincipal if doc is not available within expatdriver. r=bz (336a562965) - Bug 1215781 - Use MOZ_UTF16 to generate sTagUnicodeTable. r=mrbkap (eca371a36b) - Bug 1082598 - Part 5: Fix NPAPI for Skia update. r=jrmuizel (25c4d080ab) - Bug 1183828 - Remove 'nsWindow::GetNativeData not implemented for this type' warning. r=roc (0a60404b57) - Bug 1224445 - Add NS_NATIVE_OPENGL_CONTEXT handling to nsWindow::GetNativeData() r=mwu (ee35844be4) - Bug 1179632 part.1 native IME context should not be stored in InputContext but should be able to retrieve with nsIWidget::GetNativeData() r=smaug (5f1804bb72) - Bug 1179632 part.2 WidgetCompositionEvent should store NativeIMEContext which caused the event and PuppetWidget should store it for GetNativeIMEContext() r=smaug, sr=smaug (e00ca78e3f) - Bug 1179632 part.3 TabParent::RecvEndIMEComposition() shouldn't return true with aNoCompositionEvent when there is no widget r=smaug (ee065ed491) - Bug 1179632 part.4 Clean up the code to request IME to commit composition across process boundary r=smaug (9567c4dc57) - Bug 1179632 part.5 WidgetCompositionEvent::mNativeIMEContext should be used at looking for a TextComposition instance for a WidgetCompositionEvent r=smaug (f4e27ec28c) - Bug 1179632 part.6 KeyboardEvent.isComposing shouldn't expose IME state on different document r=smaug (ca8b8a6a02) - Bug 1227544 - Scaling on 720p devices is broken. r=timdream (cb89af839f)
This commit is contained in:
@@ -17,11 +17,13 @@ if [ -d "$topsrcdir/clang" ]; then
|
||||
export CC=$topsrcdir/clang/bin/clang
|
||||
export CXX=$topsrcdir/clang/bin/clang++
|
||||
export LLVMCONFIG=$topsrcdir/clang/bin/llvm-config
|
||||
export DSYMUTIL=$topsrcdir/clang/bin/llvm-dsymutil
|
||||
elif [ -d "$topsrcdir/../clang" ]; then
|
||||
# comm-central based build
|
||||
export CC=$topsrcdir/../clang/bin/clang
|
||||
export CXX=$topsrcdir/../clang/bin/clang++
|
||||
export LLVMCONFIG=$topsrcdir/../clang/bin/llvm-config
|
||||
export DSYMUTIL=$topsrcdir/../clang/bin/llvm-dsymutil
|
||||
fi
|
||||
|
||||
# If not set use the system default clang
|
||||
|
||||
@@ -70,4 +70,5 @@ if CONFIG['GNU_CXX']:
|
||||
# installing it in dist/lib.
|
||||
NO_EXPAND_LIBS = True
|
||||
|
||||
# We allow warnings for third-party code that can be updated from upstream.
|
||||
ALLOW_COMPILER_WARNINGS = True
|
||||
|
||||
@@ -13530,7 +13530,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent,
|
||||
// if per element referrer is enabled, the element referrer overrules
|
||||
// the document wide referrer
|
||||
if (IsElementAnchor(aContent)) {
|
||||
net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicy();
|
||||
net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicyAsEnum();
|
||||
if (refPolEnum != net::RP_Unset) {
|
||||
refererPolicy = refPolEnum;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly(
|
||||
, mPseudoType(aPseudoType)
|
||||
{
|
||||
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
|
||||
ResetIsRunningOnCompositor();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@@ -466,19 +465,6 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
KeyframeEffectReadOnly::IsPropertyRunningOnCompositor(
|
||||
nsCSSProperty aProperty) const
|
||||
{
|
||||
const auto& info = LayerAnimationInfo::sRecords;
|
||||
for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) {
|
||||
if (info[i].mProperty == aProperty) {
|
||||
return mIsPropertyRunningOnCompositor[i];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyframeEffectReadOnly::IsRunningOnCompositor() const
|
||||
{
|
||||
@@ -486,8 +472,8 @@ KeyframeEffectReadOnly::IsRunningOnCompositor() const
|
||||
// one property running on compositor.
|
||||
// Animation.IsRunningOnCompotitor will return more fine grained
|
||||
// information in bug 1196114.
|
||||
for (bool isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) {
|
||||
if (isPropertyRunningOnCompositor) {
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (property.mIsRunningOnCompositor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -498,19 +484,13 @@ void
|
||||
KeyframeEffectReadOnly::SetIsRunningOnCompositor(nsCSSProperty aProperty,
|
||||
bool aIsRunning)
|
||||
{
|
||||
static_assert(
|
||||
MOZ_ARRAY_LENGTH(LayerAnimationInfo::sRecords) ==
|
||||
MOZ_ARRAY_LENGTH(mIsPropertyRunningOnCompositor),
|
||||
"The length of mIsPropertyRunningOnCompositor should equal to"
|
||||
"the length of LayserAnimationInfo::sRecords");
|
||||
MOZ_ASSERT(nsCSSProps::PropHasFlags(aProperty,
|
||||
CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR),
|
||||
"Property being animated on compositor is a recognized "
|
||||
"compositor-animatable property");
|
||||
const auto& info = LayerAnimationInfo::sRecords;
|
||||
for (size_t i = 0; i < ArrayLength(mIsPropertyRunningOnCompositor); i++) {
|
||||
if (info[i].mProperty == aProperty) {
|
||||
mIsPropertyRunningOnCompositor[i] = aIsRunning;
|
||||
for (AnimationProperty& property : mProperties) {
|
||||
if (property.mProperty == aProperty) {
|
||||
property.mIsRunningOnCompositor = aIsRunning;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -523,8 +503,8 @@ KeyframeEffectReadOnly::~KeyframeEffectReadOnly()
|
||||
void
|
||||
KeyframeEffectReadOnly::ResetIsRunningOnCompositor()
|
||||
{
|
||||
for (bool& isPropertyRunningOnCompositor : mIsPropertyRunningOnCompositor) {
|
||||
isPropertyRunningOnCompositor = false;
|
||||
for (AnimationProperty& property : mProperties) {
|
||||
property.mIsRunningOnCompositor = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,9 +536,7 @@ KeyframeEffectReadOnly::UpdateTargetRegistration()
|
||||
// Any effects not in the effect set will not be included in the set of
|
||||
// candidate effects for running on the compositor and hence they won't
|
||||
// have their compositor status updated so we should do that now.
|
||||
for (bool& isRunningOnCompositor : mIsPropertyRunningOnCompositor) {
|
||||
isRunningOnCompositor = false;
|
||||
}
|
||||
ResetIsRunningOnCompositor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1822,7 +1800,7 @@ KeyframeEffectReadOnly::CanThrottle() const
|
||||
}
|
||||
|
||||
// First we need to check layer generation and transform overflow
|
||||
// prior to the IsPropertyRunningOnCompositor check because we should
|
||||
// prior to the property.mIsRunningOnCompositor check because we should
|
||||
// occasionally unthrottle these animations even if the animations are
|
||||
// already running on compositor.
|
||||
for (const LayerAnimationInfo::Record& record :
|
||||
@@ -1854,7 +1832,7 @@ KeyframeEffectReadOnly::CanThrottle() const
|
||||
}
|
||||
|
||||
for (const AnimationProperty& property : mProperties) {
|
||||
if (!IsPropertyRunningOnCompositor(property.mProperty)) {
|
||||
if (!property.mIsRunningOnCompositor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ struct AnimationPropertySegment
|
||||
|
||||
struct AnimationProperty
|
||||
{
|
||||
nsCSSProperty mProperty;
|
||||
nsCSSProperty mProperty = eCSSProperty_UNKNOWN;
|
||||
|
||||
// Does this property win in the CSS Cascade?
|
||||
//
|
||||
@@ -136,16 +136,26 @@ struct AnimationProperty
|
||||
// For other properties, we make it always be true.
|
||||
// **NOTE 2**: This member is not included when comparing AnimationProperty
|
||||
// objects for equality.
|
||||
bool mWinsInCascade;
|
||||
bool mWinsInCascade = true;
|
||||
|
||||
// If true, the propery is currently being animated on the compositor.
|
||||
//
|
||||
// Note that when the owning Animation requests a non-throttled restyle, in
|
||||
// between calling RequestRestyle on its AnimationCollection and when the
|
||||
// restyle is performed, this member may temporarily become false even if
|
||||
// the animation remains on the layer after the restyle.
|
||||
bool mIsRunningOnCompositor = false;
|
||||
|
||||
InfallibleTArray<AnimationPropertySegment> mSegments;
|
||||
|
||||
// NOTE: This operator does *not* compare the mWinsInCascade member.
|
||||
// NOTE: This operator does *not* compare the mWinsInCascade member *or* the
|
||||
// mIsRunningOnCompositor member.
|
||||
// This is because AnimationProperty objects are compared when recreating
|
||||
// CSS animations to determine if mutation observer change records need to
|
||||
// be created or not. However, at the point when these objects are compared
|
||||
// the mWinsInCascade will not have been set on the new objects so we ignore
|
||||
// this member to avoid generating spurious change records.
|
||||
// neither the mWinsInCascade nor the mIsRunningOnCompositor will have been
|
||||
// set on the new objects so we ignore these members to avoid generating
|
||||
// spurious change records.
|
||||
bool operator==(const AnimationProperty& aOther) const {
|
||||
return mProperty == aOther.mProperty &&
|
||||
mSegments == aOther.mSegments;
|
||||
@@ -279,8 +289,6 @@ public:
|
||||
// Any updated properties are added to |aSetProperties|.
|
||||
void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||
nsCSSPropertySet& aSetProperties);
|
||||
// Returns true if |aProperty| is currently being animated on compositor.
|
||||
bool IsPropertyRunningOnCompositor(nsCSSProperty aProperty) const;
|
||||
// Returns true if at least one property is being animated on compositor.
|
||||
bool IsRunningOnCompositor() const;
|
||||
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
|
||||
@@ -341,17 +349,6 @@ protected:
|
||||
|
||||
InfallibleTArray<AnimationProperty> mProperties;
|
||||
|
||||
// Parallel array corresponding to CommonAnimationManager::sLayerAnimationInfo
|
||||
// such that mIsPropertyRunningOnCompositor[x] is true only if this effect has
|
||||
// an animation of CommonAnimationManager::sLayerAnimationInfo[x].mProperty
|
||||
// that is currently running on the compositor.
|
||||
//
|
||||
// Note that when the owning Animation requests a non-throttled restyle, in
|
||||
// between calling RequestRestyle on its AnimationCollection and when the
|
||||
// restyle is performed, this member may temporarily become false even if
|
||||
// the animation remains on the layer after the restyle.
|
||||
bool mIsPropertyRunningOnCompositor[LayerAnimationInfo::kRecords];
|
||||
|
||||
private:
|
||||
nsIFrame* GetAnimationFrame() const;
|
||||
|
||||
|
||||
@@ -207,6 +207,9 @@ promise_test(function(t) {
|
||||
resolve();
|
||||
}));
|
||||
observer.observe(div, { animations: true, subtree: false });
|
||||
t.add_cleanup(function() {
|
||||
observer.disconnect();
|
||||
});
|
||||
div.style.animationDuration = "200s";
|
||||
}));
|
||||
}));
|
||||
|
||||
@@ -10,7 +10,6 @@ this.EXPORTED_SYMBOLS = ["InterAppCommService"];
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/AppsUtils.jsm");
|
||||
|
||||
const DEBUG = false;
|
||||
function debug(aMsg) {
|
||||
@@ -220,6 +219,24 @@ this.InterAppCommService = {
|
||||
this._messagePortPairs = {};
|
||||
},
|
||||
|
||||
/* These attributes main use is to allow testing this in an isolated way
|
||||
* that doesn't depend on the app service, or the system messenger working on
|
||||
* the test environment
|
||||
*/
|
||||
get appsService() {
|
||||
return this._appsService || appsService;
|
||||
},
|
||||
set appsService(aService) {
|
||||
this._appsService = aService;
|
||||
},
|
||||
get messenger() {
|
||||
return this._messenger || messenger;
|
||||
},
|
||||
set messenger(aMessenger) {
|
||||
this._messenger = aMessenger;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Registration of a page that wants to be connected to other apps through
|
||||
* the Inter-App Communication API.
|
||||
@@ -389,8 +406,8 @@ this.InterAppCommService = {
|
||||
_matchRules: function(aPubAppManifestURL, aPubRules,
|
||||
aSubAppManifestURL, aSubRules,
|
||||
aPubPageURL, aSubPageURL) {
|
||||
let pubApp = appsService.getAppByManifestURL(aPubAppManifestURL);
|
||||
let subApp = appsService.getAppByManifestURL(aSubAppManifestURL);
|
||||
let pubApp = this.appsService.getAppByManifestURL(aPubAppManifestURL);
|
||||
let subApp = this.appsService.getAppByManifestURL(aSubAppManifestURL);
|
||||
|
||||
let isPubAppCertified =
|
||||
(pubApp.appStatus == Ci.nsIPrincipal.APP_STATUS_CERTIFIED);
|
||||
@@ -514,7 +531,7 @@ this.InterAppCommService = {
|
||||
};
|
||||
|
||||
// Fire system message to deliver the message port to the subscriber.
|
||||
messenger.sendMessage("connection",
|
||||
this.messenger.sendMessage("connection",
|
||||
{ keyword: aKeyword,
|
||||
messagePortID: messagePortID,
|
||||
pubPageURL: aPubPageURL},
|
||||
@@ -677,7 +694,7 @@ this.InterAppCommService = {
|
||||
};
|
||||
|
||||
let glue = Cc["@mozilla.org/dom/apps/inter-app-comm-ui-glue;1"]
|
||||
.createInstance(Ci.nsIInterAppCommUIGlue);
|
||||
.createInstance(Ci.nsIInterAppCommUIGlue);
|
||||
if (glue) {
|
||||
glue.selectApps(callerID, pubAppManifestURL, keyword, appsToSelect).then(
|
||||
function(aData) {
|
||||
@@ -699,7 +716,7 @@ this.InterAppCommService = {
|
||||
);
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
debug("Error! The UI glue component is not implemented.")
|
||||
debug("Error! The UI glue component is not implemented.");
|
||||
}
|
||||
|
||||
// Resolve the caller as if there were no selected apps.
|
||||
@@ -951,14 +968,14 @@ this.InterAppCommService = {
|
||||
if (selectedApps.length == 0) {
|
||||
// Only do the connections for the existing allowed subscribers because
|
||||
// no new apps are selected to connect.
|
||||
if (DEBUG) debug("No new apps are selected to connect.")
|
||||
if (DEBUG) debug("No new apps are selected to connect.");
|
||||
|
||||
allowedSubAppManifestURLs =
|
||||
this._getAllowedSubAppManifestURLs(keyword, pubAppManifestURL);
|
||||
} else {
|
||||
// Do connections for for the existing allowed subscribers and the newly
|
||||
// selected subscribers.
|
||||
if (DEBUG) debug("Some new apps are selected to connect.")
|
||||
if (DEBUG) debug("Some new apps are selected to connect.");
|
||||
|
||||
allowedSubAppManifestURLs =
|
||||
this._addSelectedApps(keyword, pubAppManifestURL, selectedApps);
|
||||
@@ -1044,7 +1061,8 @@ this.InterAppCommService = {
|
||||
return;
|
||||
}
|
||||
|
||||
let manifestURL = appsService.getManifestURLByLocalId(params.appId);
|
||||
let manifestURL =
|
||||
this.appsService.getManifestURLByLocalId(params.appId);
|
||||
if (!manifestURL) {
|
||||
if (DEBUG) {
|
||||
debug("Error updating registered/allowed connections for an " +
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
|
||||
#include "AudioChannelAgent.h"
|
||||
#include "AudioChannelService.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMWindow.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
@@ -77,6 +81,81 @@ AudioChannelAgent::InitWithWeakCallback(nsIDOMWindow* aWindow,
|
||||
/* useWeakRef = */ true);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AudioChannelAgent::FindCorrectWindow(nsIDOMWindow* aWindow)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
|
||||
MOZ_ASSERT(window->IsInnerWindow());
|
||||
|
||||
mWindow = window->GetScriptableTop();
|
||||
if (NS_WARN_IF(!mWindow)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mWindow = mWindow->GetOuterWindow();
|
||||
if (NS_WARN_IF(!mWindow)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// From here we do an hack for nested iframes.
|
||||
// The system app doesn't have access to the nested iframe objects so it
|
||||
// cannot control the volume of the agents running in nested apps. What we do
|
||||
// here is to assign those Agents to the top scriptable window of the parent
|
||||
// iframe (what is controlled by the system app).
|
||||
// For doing this we go recursively back into the chain of windows until we
|
||||
// find apps that are not the system one.
|
||||
window = mWindow->GetParent();
|
||||
if (!window || window == mWindow) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
window = window->GetCurrentInnerWindow();
|
||||
if (!window) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
if (!doc) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal = doc->NodePrincipal();
|
||||
|
||||
uint32_t appId;
|
||||
nsresult rv = principal->GetAppId(&appId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (appId == nsIScriptSecurityManager::NO_APP_ID ||
|
||||
appId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!appsService)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAdoptingString systemAppManifest =
|
||||
mozilla::Preferences::GetString("b2g.system_manifest_url");
|
||||
if (!systemAppManifest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t systemAppId;
|
||||
rv = appsService->GetAppLocalIdByManifestURL(systemAppManifest, &systemAppId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (systemAppId == appId) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return FindCorrectWindow(window);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
|
||||
nsIAudioChannelAgentCallback *aCallback,
|
||||
@@ -108,18 +187,9 @@ AudioChannelAgent::InitInternal(nsIDOMWindow* aWindow, int32_t aChannelType,
|
||||
MOZ_ASSERT(pInnerWindow->IsInnerWindow());
|
||||
mInnerWindowID = pInnerWindow->WindowID();
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> topWindow = pInnerWindow->GetScriptableTop();
|
||||
if (NS_WARN_IF(!topWindow)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mWindow = do_QueryInterface(topWindow);
|
||||
if (mWindow) {
|
||||
mWindow = mWindow->GetOuterWindow();
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mWindow)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
nsresult rv = FindCorrectWindow(aWindow);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mAudioChannelType = aChannelType;
|
||||
|
||||
@@ -56,6 +56,8 @@ private:
|
||||
|
||||
void Shutdown();
|
||||
|
||||
nsresult FindCorrectWindow(nsIDOMWindow* aWindow);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsIAudioChannelAgentCallback> mCallback;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
@@ -219,6 +220,7 @@ AudioChannelService::Shutdown()
|
||||
|
||||
gAudioChannelService->mWindows.Clear();
|
||||
gAudioChannelService->mPlayingChildren.Clear();
|
||||
gAudioChannelService->mTabParents.Clear();
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
gAudioChannelService->mSpeakerManager.Clear();
|
||||
#endif
|
||||
@@ -341,6 +343,21 @@ AudioChannelService::UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
MaybeSendStatusUpdate();
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RegisterTabParent(TabParent* aTabParent)
|
||||
{
|
||||
MOZ_ASSERT(aTabParent);
|
||||
MOZ_ASSERT(!mTabParents.Contains(aTabParent));
|
||||
mTabParents.AppendElement(aTabParent);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::UnregisterTabParent(TabParent* aTabParent)
|
||||
{
|
||||
MOZ_ASSERT(aTabParent);
|
||||
mTabParents.RemoveElement(aTabParent);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::GetState(nsPIDOMWindow* aWindow, uint32_t aAudioChannel,
|
||||
float* aVolume, bool* aMuted)
|
||||
@@ -560,6 +577,32 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RefreshAgentsVolumeAndPropagate(AudioChannel aAudioChannel,
|
||||
nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->IsOuterWindow());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> topWindow = aWindow->GetScriptableTop();
|
||||
if (!topWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
AudioChannelWindow* winData = GetWindowData(topWindow->WindowID());
|
||||
if (!winData) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mTabParents.Length(); ++i) {
|
||||
mTabParents[i]->AudioChannelChangeNotification(aWindow, aAudioChannel,
|
||||
winData->mChannels[(uint32_t)aAudioChannel].mVolume,
|
||||
winData->mChannels[(uint32_t)aAudioChannel].mMuted);
|
||||
}
|
||||
|
||||
RefreshAgentsVolume(aWindow);
|
||||
}
|
||||
|
||||
void
|
||||
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
@@ -751,7 +794,7 @@ AudioChannelService::SetAudioChannelVolume(nsPIDOMWindow* aWindow,
|
||||
|
||||
AudioChannelWindow* winData = GetOrCreateWindowData(aWindow);
|
||||
winData->mChannels[(uint32_t)aAudioChannel].mVolume = aVolume;
|
||||
RefreshAgentsVolume(aWindow);
|
||||
RefreshAgentsVolumeAndPropagate(aAudioChannel, aWindow);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -814,7 +857,7 @@ AudioChannelService::SetAudioChannelMuted(nsPIDOMWindow* aWindow,
|
||||
|
||||
AudioChannelWindow* winData = GetOrCreateWindowData(aWindow);
|
||||
winData->mChannels[(uint32_t)aAudioChannel].mMuted = aMuted;
|
||||
RefreshAgentsVolume(aWindow);
|
||||
RefreshAgentsVolumeAndPropagate(aAudioChannel, aWindow);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
||||
@@ -23,10 +23,13 @@ struct PRLogModuleInfo;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
class SpeakerManagerService;
|
||||
#endif
|
||||
|
||||
class TabParent;
|
||||
|
||||
#define NUMBER_OF_AUDIO_CHANNELS (uint32_t)AudioChannel::EndGuard_
|
||||
|
||||
class AudioChannelService final : public nsIAudioChannelService
|
||||
@@ -63,6 +66,12 @@ public:
|
||||
void UnregisterAudioChannelAgent(AudioChannelAgent* aAgent,
|
||||
uint32_t aNotifyPlayback);
|
||||
|
||||
/**
|
||||
* For nested iframes.
|
||||
*/
|
||||
void RegisterTabParent(TabParent* aTabParent);
|
||||
void UnregisterTabParent(TabParent* aTabParent);
|
||||
|
||||
/**
|
||||
* Return the state to indicate this audioChannel for his window should keep
|
||||
* playing/muted.
|
||||
@@ -108,6 +117,9 @@ public:
|
||||
|
||||
void RefreshAgentsVolume(nsPIDOMWindow* aWindow);
|
||||
|
||||
void RefreshAgentsVolumeAndPropagate(AudioChannel aAudioChannel,
|
||||
nsPIDOMWindow* aWindow);
|
||||
|
||||
// This method needs to know the inner window that wants to capture audio. We
|
||||
// group agents per top outer window, but we can have multiple innerWindow per
|
||||
// top outerWindow (subiframes, etc.) and we have to identify all the agents
|
||||
@@ -223,6 +235,9 @@ private:
|
||||
nsTArray<SpeakerManagerService*> mSpeakerManager;
|
||||
#endif
|
||||
|
||||
// Raw pointers because TabParents must unregister themselves.
|
||||
nsTArray<TabParent*> mTabParents;
|
||||
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
|
||||
uint64_t mDefChannelChildID;
|
||||
|
||||
+12
-2
@@ -552,6 +552,16 @@ Element::GetClassList(nsISupports** aClassList)
|
||||
NS_ADDREF(*aClassList = ClassList());
|
||||
}
|
||||
|
||||
void
|
||||
Element::GetAttributeNames(nsTArray<nsString>& aResult)
|
||||
{
|
||||
uint32_t count = mAttrsAndChildren.AttrCount();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
|
||||
name->GetQualifiedName(*aResult.AppendElement());
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsIHTMLCollection>
|
||||
Element::GetElementsByTagName(const nsAString& aLocalName)
|
||||
{
|
||||
@@ -3721,11 +3731,11 @@ Element::FontSizeInflation()
|
||||
}
|
||||
|
||||
net::ReferrerPolicy
|
||||
Element::GetReferrerPolicy()
|
||||
Element::GetReferrerPolicyAsEnum()
|
||||
{
|
||||
if (Preferences::GetBool("network.http.enablePerElementReferrer", false) &&
|
||||
IsHTMLElement()) {
|
||||
const nsAttrValue* referrerValue = GetParsedAttr(nsGkAtoms::referrer);
|
||||
const nsAttrValue* referrerValue = GetParsedAttr(nsGkAtoms::referrerpolicy);
|
||||
if (referrerValue && referrerValue->Type() == nsAttrValue::eEnum) {
|
||||
return net::ReferrerPolicy(referrerValue->GetEnumValue());
|
||||
}
|
||||
|
||||
+6
-9
@@ -634,6 +634,9 @@ public:
|
||||
|
||||
return slots->mAttributeMap;
|
||||
}
|
||||
|
||||
void GetAttributeNames(nsTArray<nsString>& aResult);
|
||||
|
||||
void GetAttribute(const nsAString& aName, nsString& aReturn)
|
||||
{
|
||||
DOMString str;
|
||||
@@ -680,12 +683,6 @@ public:
|
||||
ErrorResult& aError);
|
||||
already_AddRefed<nsIHTMLCollection>
|
||||
GetElementsByClassName(const nsAString& aClassNames);
|
||||
bool MozMatchesSelector(const nsAString& aSelector,
|
||||
ErrorResult& aError)
|
||||
{
|
||||
return Matches(aSelector, aError);
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Implement the algorithm specified at
|
||||
@@ -1111,7 +1108,7 @@ public:
|
||||
*/
|
||||
float FontSizeInflation();
|
||||
|
||||
net::ReferrerPolicy GetReferrerPolicy();
|
||||
net::ReferrerPolicy GetReferrerPolicyAsEnum();
|
||||
|
||||
protected:
|
||||
/*
|
||||
@@ -1817,8 +1814,8 @@ NS_IMETHOD MozMatchesSelector(const nsAString& selector, \
|
||||
bool* _retval) final override \
|
||||
{ \
|
||||
mozilla::ErrorResult rv; \
|
||||
*_retval = Element::MozMatchesSelector(selector, rv); \
|
||||
return rv.StealNSResult(); \
|
||||
*_retval = Element::Matches(selector, rv); \
|
||||
return rv.StealNSResult(); \
|
||||
} \
|
||||
NS_IMETHOD SetCapture(bool retargetToElement) final override \
|
||||
{ \
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "nsEscape.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsHTMLDNSPrefetch.h"
|
||||
#include "nsString.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
|
||||
@@ -46,6 +47,31 @@ Link::ElementHasHref() const
|
||||
mElement->HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)));
|
||||
}
|
||||
|
||||
void
|
||||
Link::TryDNSPrefetch()
|
||||
{
|
||||
MOZ_ASSERT(mElement->IsInComposedDoc());
|
||||
if (ElementHasHref() && nsHTMLDNSPrefetch::IsAllowed(mElement->OwnerDoc())) {
|
||||
nsHTMLDNSPrefetch::PrefetchLow(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Link::CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
nsWrapperCache::FlagsType aRequestedFlag)
|
||||
{
|
||||
// If prefetch was deferred, clear flag and move on
|
||||
if (mElement->HasFlag(aDeferredFlag)) {
|
||||
mElement->UnsetFlags(aDeferredFlag);
|
||||
// Else if prefetch was requested, clear flag and send cancellation
|
||||
} else if (mElement->HasFlag(aRequestedFlag)) {
|
||||
mElement->UnsetFlags(aRequestedFlag);
|
||||
// Possible that hostname could have changed since binding, but since this
|
||||
// covers common cases, most DNS prefetch requests will be canceled
|
||||
nsHTMLDNSPrefetch::CancelPrefetchLow(this, NS_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Link::SetLinkState(nsLinkState aState)
|
||||
{
|
||||
|
||||
@@ -111,6 +111,11 @@ public:
|
||||
|
||||
bool ElementHasHref() const;
|
||||
|
||||
void TryDNSPrefetch();
|
||||
|
||||
void CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
nsWrapperCache::FlagsType aRequestedFlag);
|
||||
|
||||
protected:
|
||||
virtual ~Link();
|
||||
|
||||
|
||||
+5
-16
@@ -2682,23 +2682,12 @@ nsDocument::ApplySettingsFromCSP(bool aSpeculative)
|
||||
}
|
||||
|
||||
// 2) apply settings from speculative csp
|
||||
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
|
||||
rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
|
||||
if (preloadCsp) {
|
||||
// Set up any Referrer Policy specified by CSP
|
||||
bool hasReferrerPolicy = false;
|
||||
uint32_t referrerPolicy = mozilla::net::RP_Default;
|
||||
rv = preloadCsp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
|
||||
if (!mUpgradeInsecurePreloads) {
|
||||
nsCOMPtr<nsIContentSecurityPolicy> preloadCsp;
|
||||
rv = NodePrincipal()->GetPreloadCsp(getter_AddRefs(preloadCsp));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (hasReferrerPolicy) {
|
||||
// please note that referrer policy spec defines that the latest
|
||||
// policy awlays wins, hence we can safely overwrite the policy here.
|
||||
mReferrerPolicy = static_cast<ReferrerPolicy>(referrerPolicy);
|
||||
mReferrerPolicySet = true;
|
||||
}
|
||||
if (!mUpgradeInsecurePreloads) {
|
||||
rv = preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (preloadCsp) {
|
||||
preloadCsp->GetUpgradeInsecureRequests(&mUpgradeInsecurePreloads);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ nsFrameLoader::ReallyStartLoadingInternal()
|
||||
net::ReferrerPolicy referrerPolicy = mOwnerContent->OwnerDoc()->GetReferrerPolicy();
|
||||
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
|
||||
if (iframe) {
|
||||
net::ReferrerPolicy iframeReferrerPolicy = iframe->GetReferrerPolicy();
|
||||
net::ReferrerPolicy iframeReferrerPolicy = iframe->GetReferrerPolicyAsEnum();
|
||||
if (iframeReferrerPolicy != net::RP_Unset) {
|
||||
referrerPolicy = iframeReferrerPolicy;
|
||||
}
|
||||
|
||||
@@ -594,6 +594,7 @@ GK_ATOM(menuseparator, "menuseparator")
|
||||
GK_ATOM(message, "message")
|
||||
GK_ATOM(meta, "meta")
|
||||
GK_ATOM(referrer, "referrer")
|
||||
GK_ATOM(referrerpolicy, "referrerpolicy")
|
||||
GK_ATOM(meter, "meter")
|
||||
GK_ATOM(method, "method")
|
||||
GK_ATOM(microdataProperties, "microdataProperties")
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface mozIApplication;
|
||||
interface nsFrameLoader;
|
||||
interface nsIDocShell;
|
||||
interface nsIURI;
|
||||
@@ -214,7 +215,7 @@ class nsFrameLoader;
|
||||
|
||||
native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
|
||||
|
||||
[scriptable, uuid(c4abebcf-55f3-47d4-af15-151311971255)]
|
||||
[scriptable, uuid(adc1b3ba-8deb-4943-8045-e6de0044f2ce)]
|
||||
interface nsIFrameLoaderOwner : nsISupports
|
||||
{
|
||||
/**
|
||||
@@ -223,6 +224,12 @@ interface nsIFrameLoaderOwner : nsISupports
|
||||
readonly attribute nsIFrameLoader frameLoader;
|
||||
[noscript, notxpcom] alreadyAddRefed_nsFrameLoader GetFrameLoader();
|
||||
|
||||
/**
|
||||
* The principal of parent mozIApplication in case of nested mozbrowser
|
||||
* iframes.
|
||||
*/
|
||||
readonly attribute mozIApplication parentApplication;
|
||||
|
||||
/**
|
||||
* Puts the FrameLoaderOwner in prerendering mode.
|
||||
*/
|
||||
|
||||
@@ -1213,6 +1213,17 @@ nsObjectLoadingContent::GetFrameLoader()
|
||||
return loader.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::GetParentApplication(mozIApplication** aApplication)
|
||||
{
|
||||
if (!aApplication) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aApplication = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::SetIsPrerendered()
|
||||
{
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/dom/BrowserElementAudioChannelBinding.h"
|
||||
#include "mozilla/dom/DOMRequest.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
@@ -23,16 +25,6 @@
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
AssertIsInMainProcess()
|
||||
{
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@@ -89,7 +81,6 @@ BrowserElementAudioChannel::BrowserElementAudioChannel(
|
||||
, mState(eStateUnknown)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
@@ -107,7 +98,6 @@ BrowserElementAudioChannel::BrowserElementAudioChannel(
|
||||
BrowserElementAudioChannel::~BrowserElementAudioChannel()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||
if (obs) {
|
||||
@@ -173,8 +163,6 @@ AudioChannel
|
||||
BrowserElementAudioChannel::Name() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
return mAudioChannel;
|
||||
}
|
||||
|
||||
@@ -361,7 +349,6 @@ already_AddRefed<dom::DOMRequest>
|
||||
BrowserElementAudioChannel::GetVolume(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (!mFrameWindow) {
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
@@ -387,7 +374,6 @@ already_AddRefed<dom::DOMRequest>
|
||||
BrowserElementAudioChannel::SetVolume(float aVolume, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (!mFrameWindow) {
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
@@ -420,7 +406,6 @@ already_AddRefed<dom::DOMRequest>
|
||||
BrowserElementAudioChannel::GetMuted(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (!mFrameWindow) {
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
@@ -446,7 +431,6 @@ already_AddRefed<dom::DOMRequest>
|
||||
BrowserElementAudioChannel::SetMuted(bool aMuted, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (!mFrameWindow) {
|
||||
nsCOMPtr<nsIDOMDOMRequest> request;
|
||||
@@ -479,7 +463,6 @@ already_AddRefed<dom::DOMRequest>
|
||||
BrowserElementAudioChannel::IsActive(ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AssertIsInMainProcess();
|
||||
|
||||
if (mState != eStateUnknown) {
|
||||
RefPtr<DOMRequest> domRequest = new DOMRequest(GetOwner());
|
||||
@@ -593,8 +576,29 @@ BrowserElementAudioChannel::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
|
||||
if (NS_WARN_IF(!wrapper)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
// This can be a nested iframe.
|
||||
if (!wrapper) {
|
||||
nsCOMPtr<nsITabParent> iTabParent = do_QueryInterface(aSubject);
|
||||
if (!iTabParent) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<TabParent> tabParent = TabParent::GetFrom(iTabParent);
|
||||
if (!tabParent) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
Element* element = tabParent->GetOwnerElement();
|
||||
if (!element) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = element->OwnerDoc()->GetWindow();
|
||||
if (window == mFrameWindow) {
|
||||
ProcessStateChanged(aData);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint64_t windowID;
|
||||
|
||||
@@ -144,7 +144,10 @@ function runTests() {
|
||||
}
|
||||
|
||||
|
||||
addEventListener('load', function() {
|
||||
SimpleTest.executeSoon(runTests);
|
||||
addEventListener('testready', function() {
|
||||
SpecialPowers.pushPrefEnv({'set': [["b2g.system_manifest_url", "http://mochi.test:8888/manifest.webapp"]]},
|
||||
function() {
|
||||
SimpleTest.executeSoon(runTests);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/* Any copyright is dedicated to the public domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Bug 1113086 - tests for AudioChannel API into BrowserElement
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
browserElementTestHelpers.setEnabledPref(true);
|
||||
browserElementTestHelpers.addPermission();
|
||||
|
||||
function runTests() {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||
|
||||
var listener = function(e) {
|
||||
var message = e.detail.message;
|
||||
if (/^OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/^KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
}
|
||||
}
|
||||
|
||||
function audio_loadend() {
|
||||
ok("mute" in iframe, "iframe.mute exists");
|
||||
ok("unmute" in iframe, "iframe.unmute exists");
|
||||
ok("getMuted" in iframe, "iframe.getMuted exists");
|
||||
ok("getVolume" in iframe, "iframe.getVolume exists");
|
||||
ok("setVolume" in iframe, "iframe.setVolume exists");
|
||||
|
||||
ok("allowedAudioChannels" in iframe, "allowedAudioChannels exist");
|
||||
var channels = iframe.allowedAudioChannels;
|
||||
is(channels.length, 1, "1 audio channel by default");
|
||||
|
||||
var ac = channels[0];
|
||||
|
||||
ok(ac instanceof BrowserElementAudioChannel, "Correct class");
|
||||
ok("getVolume" in ac, "ac.getVolume exists");
|
||||
ok("setVolume" in ac, "ac.setVolume exists");
|
||||
ok("getMuted" in ac, "ac.getMuted exists");
|
||||
ok("setMuted" in ac, "ac.setMuted exists");
|
||||
ok("isActive" in ac, "ac.isActive exists");
|
||||
|
||||
info("Setting the volume...");
|
||||
ac.setVolume(0.5);
|
||||
|
||||
ac.onactivestatechanged = function() {
|
||||
ok(true, "activestatechanged event received.");
|
||||
ac.onactivestatechanged = null;
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', audio_loadend);
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', listener, false);
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
var context = { 'url': 'http://example.org',
|
||||
'appId': SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID,
|
||||
'isInBrowserElement': true };
|
||||
SpecialPowers.pushPermissions([
|
||||
{'type': 'browser', 'allow': 1, 'context': context},
|
||||
{'type': 'embed-apps', 'allow': 1, 'context': context}
|
||||
], function() {
|
||||
iframe.src = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_AudioChannel_nested.html';
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener('testready', function() {
|
||||
SpecialPowers.pushPrefEnv({'set': [["b2g.system_manifest_url", "http://mochi.test:8888/manifest.webapp"]]},
|
||||
function() {
|
||||
SimpleTest.executeSoon(runTests);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,63 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
|
||||
function ok(a, msg) {
|
||||
alert((!!a ? "OK" : "KO") + " " + msg);
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
ok(a === b, msg);
|
||||
}
|
||||
|
||||
function finish(a, b, msg) {
|
||||
alert("DONE");
|
||||
}
|
||||
|
||||
addEventListener('load', function(e) {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
// set 'remote' to true here will make the the iframe remote in _inproc_
|
||||
// test and in-process in _oop_ test.
|
||||
iframe.setAttribute('remote', 'true');
|
||||
iframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||
|
||||
iframe.addEventListener('mozbrowserloadend', function(e) {
|
||||
ok("mute" in iframe, "iframe.mute exists");
|
||||
ok("unmute" in iframe, "iframe.unmute exists");
|
||||
ok("getMuted" in iframe, "iframe.getMuted exists");
|
||||
ok("getVolume" in iframe, "iframe.getVolume exists");
|
||||
ok("setVolume" in iframe, "iframe.setVolume exists");
|
||||
|
||||
ok("allowedAudioChannels" in iframe, "allowedAudioChannels exist");
|
||||
var channels = iframe.allowedAudioChannels;
|
||||
is(channels.length, 1, "1 audio channel by default");
|
||||
|
||||
var ac = channels[0];
|
||||
|
||||
ok(ac instanceof BrowserElementAudioChannel, "Correct class");
|
||||
ok("getVolume" in ac, "ac.getVolume exists");
|
||||
ok("setVolume" in ac, "ac.setVolume exists");
|
||||
ok("getMuted" in ac, "ac.getMuted exists");
|
||||
ok("setMuted" in ac, "ac.setMuted exists");
|
||||
ok("isActive" in ac, "ac.isActive exists");
|
||||
|
||||
ac.onactivestatechanged = function() {
|
||||
ok("activestatechanged event received.");
|
||||
|
||||
ac.getVolume().onsuccess = function(e) {
|
||||
ok(e.target.result, 1, "Default volume is 1");
|
||||
};
|
||||
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
iframe.src = 'http://example.org/tests/dom/browser-element/mochitest/file_audio.html';
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -115,6 +115,7 @@ disabled = bug 924771
|
||||
disabled = bug 924771
|
||||
[test_browserElement_oop_GetContentDimensions.html]
|
||||
[test_browserElement_oop_AudioChannel.html]
|
||||
[test_browserElement_oop_AudioChannel_nested.html]
|
||||
[test_browserElement_oop_SetNFCFocus.html]
|
||||
[test_browserElement_oop_getWebManifest.html]
|
||||
[test_browserElement_oop_OpenWindowEmpty.html]
|
||||
|
||||
@@ -82,11 +82,13 @@ support-files =
|
||||
browserElement_XFrameOptionsSameOrigin.js
|
||||
browserElement_GetContentDimensions.js
|
||||
browserElement_AudioChannel.js
|
||||
browserElement_AudioChannel_nested.js
|
||||
file_browserElement_AlertInFrame.html
|
||||
file_browserElement_AlertInFrame_Inner.html
|
||||
file_browserElement_AllowEmbedAppsInNestedOOIframe.html
|
||||
file_browserElement_AppFramePermission.html
|
||||
file_browserElement_AppWindowNamespace.html
|
||||
file_browserElement_AudioChannel_nested.html
|
||||
file_browserElement_Viewmode.html
|
||||
file_browserElement_ThemeColor.html
|
||||
file_browserElement_BrowserWindowNamespace.html
|
||||
@@ -246,6 +248,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 936226
|
||||
disabled = bug 774100
|
||||
[test_browserElement_inproc_GetContentDimensions.html]
|
||||
[test_browserElement_inproc_AudioChannel.html]
|
||||
[test_browserElement_inproc_AudioChannel_nested.html]
|
||||
[test_browserElement_inproc_SetNFCFocus.html]
|
||||
[test_browserElement_inproc_getStructuredData.html]
|
||||
[test_browserElement_inproc_OpenWindowEmpty.html]
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test of browser element audioChannel in nested mozbrowser iframes.</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_AudioChannel_nested.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test of browser element audioChannel.</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript;version=1.7" src="browserElement_AudioChannel_nested.js">
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -737,15 +737,17 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
||||
if (content)
|
||||
mCurrentTargetContent = content;
|
||||
|
||||
// NOTE: Don't refer TextComposition::IsComposing() since DOM Level 3
|
||||
// Events defines that KeyboardEvent.isComposing is true when it's
|
||||
// NOTE: Don't refer TextComposition::IsComposing() since UI Events
|
||||
// defines that KeyboardEvent.isComposing is true when it's
|
||||
// dispatched after compositionstart and compositionend.
|
||||
// TextComposition::IsComposing() is false even before
|
||||
// compositionend if there is no composing string.
|
||||
WidgetKeyboardEvent* keyEvent = aEvent->AsKeyboardEvent();
|
||||
// And also don't expose other document's composition state.
|
||||
// A native IME context is typically shared by multiple documents.
|
||||
// So, don't use GetTextCompositionFor(nsIWidget*) here.
|
||||
RefPtr<TextComposition> composition =
|
||||
IMEStateManager::GetTextCompositionFor(keyEvent);
|
||||
keyEvent->mIsComposing = !!composition;
|
||||
IMEStateManager::GetTextCompositionFor(aPresContext);
|
||||
aEvent->AsKeyboardEvent()->mIsComposing = !!composition;
|
||||
}
|
||||
break;
|
||||
case eWheel:
|
||||
|
||||
@@ -1137,11 +1137,21 @@ IMEStateManager::DispatchCompositionEvent(
|
||||
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("ISM: IMEStateManager::DispatchCompositionEvent(aNode=0x%p, "
|
||||
"aPresContext=0x%p, aCompositionEvent={ message=%s, "
|
||||
"aPresContext=0x%p, aCompositionEvent={ mMessage=%s, "
|
||||
"mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, widget(0x%p)={ "
|
||||
"GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, Destroyed()=%s }, "
|
||||
"mFlags={ mIsTrusted=%s, mPropagationStopped=%s } }, "
|
||||
"aIsSynthesized=%s), tabParent=%p",
|
||||
aEventTargetNode, aPresContext,
|
||||
ToChar(aCompositionEvent->mMessage),
|
||||
aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
|
||||
aCompositionEvent->mNativeIMEContext.mOriginProcessID,
|
||||
aCompositionEvent->widget.get(),
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mOriginProcessID,
|
||||
GetBoolName(aCompositionEvent->widget->Destroyed()),
|
||||
GetBoolName(aCompositionEvent->mFlags.mIsTrusted),
|
||||
GetBoolName(aCompositionEvent->mFlags.mPropagationStopped),
|
||||
GetBoolName(aIsSynthesized), tabParent.get()));
|
||||
@@ -1157,7 +1167,7 @@ IMEStateManager::DispatchCompositionEvent(
|
||||
EnsureTextCompositionArray();
|
||||
|
||||
RefPtr<TextComposition> composition =
|
||||
sTextCompositions->GetCompositionFor(aCompositionEvent->widget);
|
||||
sTextCompositions->GetCompositionFor(aCompositionEvent);
|
||||
if (!composition) {
|
||||
// If synthesized event comes after delayed native composition events
|
||||
// for request of commit or cancel, we should ignore it.
|
||||
@@ -1271,8 +1281,18 @@ IMEStateManager::OnCompositionEventDiscarded(
|
||||
|
||||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("ISM: IMEStateManager::OnCompositionEventDiscarded(aCompositionEvent={ "
|
||||
"mMessage=%s, mFlags={ mIsTrusted=%s } })",
|
||||
"mMessage=%s, mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, widget(0x%p)={ "
|
||||
"GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, Destroyed()=%s }, "
|
||||
"mFlags={ mIsTrusted=%s } })",
|
||||
ToChar(aCompositionEvent->mMessage),
|
||||
aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
|
||||
aCompositionEvent->mNativeIMEContext.mOriginProcessID,
|
||||
aCompositionEvent->widget.get(),
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mOriginProcessID,
|
||||
GetBoolName(aCompositionEvent->widget->Destroyed()),
|
||||
GetBoolName(aCompositionEvent->mFlags.mIsTrusted)));
|
||||
|
||||
if (!aCompositionEvent->mFlags.mIsTrusted) {
|
||||
@@ -1631,11 +1651,27 @@ IMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
|
||||
|
||||
// static
|
||||
already_AddRefed<TextComposition>
|
||||
IMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aGUIEvent)
|
||||
IMEStateManager::GetTextCompositionFor(
|
||||
const WidgetCompositionEvent* aCompositionEvent)
|
||||
{
|
||||
MOZ_ASSERT(aGUIEvent->AsCompositionEvent() || aGUIEvent->AsKeyboardEvent(),
|
||||
"aGUIEvent has to be WidgetCompositionEvent or WidgetKeyboardEvent");
|
||||
return GetTextCompositionFor(aGUIEvent->widget);
|
||||
if (!sTextCompositions) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<TextComposition> textComposition =
|
||||
sTextCompositions->GetCompositionFor(aCompositionEvent);
|
||||
return textComposition.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<TextComposition>
|
||||
IMEStateManager::GetTextCompositionFor(nsPresContext* aPresContext)
|
||||
{
|
||||
if (!sTextCompositions) {
|
||||
return nullptr;
|
||||
}
|
||||
RefPtr<TextComposition> textComposition =
|
||||
sTextCompositions->GetCompositionFor(aPresContext);
|
||||
return textComposition.forget();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -181,11 +181,17 @@ public:
|
||||
|
||||
/**
|
||||
* Returns TextComposition instance for the event.
|
||||
*
|
||||
* @param aGUIEvent Should be a composition event which is being dispatched.
|
||||
*/
|
||||
static already_AddRefed<TextComposition>
|
||||
GetTextCompositionFor(WidgetGUIEvent* aGUIEvent);
|
||||
GetTextCompositionFor(const WidgetCompositionEvent* aCompositionEvent);
|
||||
|
||||
/**
|
||||
* Returns TextComposition instance for the pres context.
|
||||
* Be aware, even if another pres context which shares native IME context with
|
||||
* specified pres context has composition, this returns nullptr.
|
||||
*/
|
||||
static already_AddRefed<TextComposition>
|
||||
GetTextCompositionFor(nsPresContext* aPresContext);
|
||||
|
||||
/**
|
||||
* Send a notification to IME. It depends on the IME or platform spec what
|
||||
|
||||
@@ -39,8 +39,7 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
|
||||
: mPresContext(aPresContext)
|
||||
, mNode(aNode)
|
||||
, mTabParent(aTabParent)
|
||||
, mNativeContext(
|
||||
aCompositionEvent->widget->GetInputContext().mNativeIMEContext)
|
||||
, mNativeContext(aCompositionEvent->mNativeIMEContext)
|
||||
, mCompositionStartOffset(0)
|
||||
, mCompositionTargetOffset(0)
|
||||
, mIsSynthesizedForTests(aCompositionEvent->mFlags.mIsSynthesizedForTests)
|
||||
@@ -54,6 +53,7 @@ TextComposition::TextComposition(nsPresContext* aPresContext,
|
||||
Preferences::GetBool("dom.compositionevent.allow_control_characters",
|
||||
false))
|
||||
{
|
||||
MOZ_ASSERT(aCompositionEvent->mNativeIMEContext.IsValid());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -66,12 +66,6 @@ TextComposition::Destroy()
|
||||
// this being destroyed for cleaning up the stuff.
|
||||
}
|
||||
|
||||
bool
|
||||
TextComposition::MatchesNativeContext(nsIWidget* aWidget) const
|
||||
{
|
||||
return mNativeContext == aWidget->GetInputContext().mNativeIMEContext;
|
||||
}
|
||||
|
||||
bool
|
||||
TextComposition::IsValidStateForComposition(nsIWidget* aWidget) const
|
||||
{
|
||||
@@ -114,6 +108,7 @@ TextComposition::CloneAndDispatchAs(
|
||||
compositionEvent.time = aCompositionEvent->time;
|
||||
compositionEvent.timeStamp = aCompositionEvent->timeStamp;
|
||||
compositionEvent.mData = aCompositionEvent->mData;
|
||||
compositionEvent.mNativeIMEContext = aCompositionEvent->mNativeIMEContext;
|
||||
compositionEvent.mOriginalMessage = aCompositionEvent->mMessage;
|
||||
compositionEvent.mFlags.mIsSynthesizedForTests =
|
||||
aCompositionEvent->mFlags.mIsSynthesizedForTests;
|
||||
@@ -613,6 +608,7 @@ TextComposition::CompositionEventDispatcher::Run()
|
||||
switch (mEventMessage) {
|
||||
case eCompositionStart: {
|
||||
WidgetCompositionEvent compStart(true, eCompositionStart, widget);
|
||||
compStart.mNativeIMEContext = mTextComposition->mNativeContext;
|
||||
WidgetQueryContentEvent selectedText(true, eQuerySelectedText, widget);
|
||||
ContentEventHandler handler(presContext);
|
||||
handler.OnQuerySelectedText(&selectedText);
|
||||
@@ -629,6 +625,7 @@ TextComposition::CompositionEventDispatcher::Run()
|
||||
case eCompositionCommitAsIs:
|
||||
case eCompositionCommit: {
|
||||
WidgetCompositionEvent compEvent(true, mEventMessage, widget);
|
||||
compEvent.mNativeIMEContext = mTextComposition->mNativeContext;
|
||||
if (mEventMessage != eCompositionCommitAsIs) {
|
||||
compEvent.mData = mData;
|
||||
}
|
||||
@@ -650,16 +647,25 @@ TextComposition::CompositionEventDispatcher::Run()
|
||||
******************************************************************************/
|
||||
|
||||
TextCompositionArray::index_type
|
||||
TextCompositionArray::IndexOf(nsIWidget* aWidget)
|
||||
TextCompositionArray::IndexOf(const NativeIMEContext& aNativeIMEContext)
|
||||
{
|
||||
if (!aNativeIMEContext.IsValid()) {
|
||||
return NoIndex;
|
||||
}
|
||||
for (index_type i = Length(); i > 0; --i) {
|
||||
if (ElementAt(i - 1)->MatchesNativeContext(aWidget)) {
|
||||
if (ElementAt(i - 1)->GetNativeIMEContext() == aNativeIMEContext) {
|
||||
return i - 1;
|
||||
}
|
||||
}
|
||||
return NoIndex;
|
||||
}
|
||||
|
||||
TextCompositionArray::index_type
|
||||
TextCompositionArray::IndexOf(nsIWidget* aWidget)
|
||||
{
|
||||
return IndexOf(aWidget->GetNativeIMEContext());
|
||||
}
|
||||
|
||||
TextCompositionArray::index_type
|
||||
TextCompositionArray::IndexOf(nsPresContext* aPresContext)
|
||||
{
|
||||
@@ -693,6 +699,27 @@ TextCompositionArray::GetCompositionFor(nsIWidget* aWidget)
|
||||
return ElementAt(i);
|
||||
}
|
||||
|
||||
TextComposition*
|
||||
TextCompositionArray::GetCompositionFor(
|
||||
const WidgetCompositionEvent* aCompositionEvent)
|
||||
{
|
||||
index_type i = IndexOf(aCompositionEvent->mNativeIMEContext);
|
||||
if (i == NoIndex) {
|
||||
return nullptr;
|
||||
}
|
||||
return ElementAt(i);
|
||||
}
|
||||
|
||||
TextComposition*
|
||||
TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext)
|
||||
{
|
||||
index_type i = IndexOf(aPresContext);
|
||||
if (i == NoIndex) {
|
||||
return nullptr;
|
||||
}
|
||||
return ElementAt(i);
|
||||
}
|
||||
|
||||
TextComposition*
|
||||
TextCompositionArray::GetCompositionFor(nsPresContext* aPresContext,
|
||||
nsINode* aNode)
|
||||
|
||||
@@ -76,7 +76,10 @@ public:
|
||||
// came from nsDOMWindowUtils.
|
||||
bool IsSynthesizedForTests() const { return mIsSynthesizedForTests; }
|
||||
|
||||
bool MatchesNativeContext(nsIWidget* aWidget) const;
|
||||
const widget::NativeIMEContext& GetNativeIMEContext() const
|
||||
{
|
||||
return mNativeContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when IMEStateManager stops managing the instance.
|
||||
@@ -191,7 +194,7 @@ private:
|
||||
|
||||
// mNativeContext stores a opaque pointer. This works as the "ID" for this
|
||||
// composition. Don't access the instance, it may not be available.
|
||||
void* mNativeContext;
|
||||
widget::NativeIMEContext mNativeContext;
|
||||
|
||||
// mEditorWeak is a weak reference to the focused editor handling composition.
|
||||
nsWeakPtr mEditorWeak;
|
||||
@@ -400,11 +403,19 @@ class TextCompositionArray final :
|
||||
public nsAutoTArray<RefPtr<TextComposition>, 2>
|
||||
{
|
||||
public:
|
||||
// Looking for per native IME context.
|
||||
index_type IndexOf(const widget::NativeIMEContext& aNativeIMEContext);
|
||||
index_type IndexOf(nsIWidget* aWidget);
|
||||
|
||||
TextComposition* GetCompositionFor(nsIWidget* aWidget);
|
||||
TextComposition* GetCompositionFor(
|
||||
const WidgetCompositionEvent* aCompositionEvent);
|
||||
|
||||
// Looking for per nsPresContext
|
||||
index_type IndexOf(nsPresContext* aPresContext);
|
||||
index_type IndexOf(nsPresContext* aPresContext, nsINode* aNode);
|
||||
|
||||
TextComposition* GetCompositionFor(nsIWidget* aWidget);
|
||||
TextComposition* GetCompositionFor(nsPresContext* aPresContext);
|
||||
TextComposition* GetCompositionFor(nsPresContext* aPresContext,
|
||||
nsINode* aNode);
|
||||
TextComposition* GetCompositionInContent(nsPresContext* aPresContext,
|
||||
|
||||
@@ -158,9 +158,7 @@ HTMLAnchorElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIDocument* doc = GetComposedDoc();
|
||||
if (doc) {
|
||||
doc->RegisterPendingLinkUpdate(this);
|
||||
if (nsHTMLDNSPrefetch::IsAllowed(OwnerDoc())) {
|
||||
nsHTMLDNSPrefetch::PrefetchLow(this);
|
||||
}
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -172,18 +170,9 @@ HTMLAnchorElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
// Cancel any DNS prefetches
|
||||
// Note: Must come before ResetLinkState. If called after, it will recreate
|
||||
// mCachedURI based on data that is invalid - due to a call to GetHostname.
|
||||
CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
|
||||
HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
|
||||
// If prefetch was deferred, clear flag and move on
|
||||
if (HasFlag(HTML_ANCHOR_DNS_PREFETCH_DEFERRED))
|
||||
UnsetFlags(HTML_ANCHOR_DNS_PREFETCH_DEFERRED);
|
||||
// Else if prefetch was requested, clear flag and send cancellation
|
||||
else if (HasFlag(HTML_ANCHOR_DNS_PREFETCH_REQUESTED)) {
|
||||
UnsetFlags(HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
// Possible that hostname could have changed since binding, but since this
|
||||
// covers common cases, most DNS prefetch requests will be canceled
|
||||
nsHTMLDNSPrefetch::CancelPrefetchLow(this, NS_ERROR_ABORT);
|
||||
}
|
||||
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
@@ -406,6 +395,10 @@ HTMLAnchorElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
reset = true;
|
||||
}
|
||||
}
|
||||
if (reset) {
|
||||
CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
|
||||
HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix,
|
||||
@@ -418,6 +411,9 @@ HTMLAnchorElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
// to get updated information about the visitedness from Link.
|
||||
if (reset) {
|
||||
Link::ResetLinkState(!!aNotify, true);
|
||||
if (IsInComposedDoc()) {
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -427,6 +423,14 @@ nsresult
|
||||
HTMLAnchorElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
|
||||
bool aNotify)
|
||||
{
|
||||
bool href =
|
||||
(aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID);
|
||||
|
||||
if (href) {
|
||||
CancelDNSPrefetch(HTML_ANCHOR_DNS_PREFETCH_DEFERRED,
|
||||
HTML_ANCHOR_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
|
||||
nsresult rv = nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute,
|
||||
aNotify);
|
||||
|
||||
@@ -435,7 +439,7 @@ HTMLAnchorElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
|
||||
// we will need the updated attribute value because notifying the document
|
||||
// that content states have changed will call IntrinsicState, which will try
|
||||
// to get updated information about the visitedness from Link.
|
||||
if (aAttribute == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
|
||||
if (href) {
|
||||
Link::ResetLinkState(!!aNotify, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,13 +121,13 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::rel, aValue, rv);
|
||||
}
|
||||
void SetReferrer(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
void SetReferrerPolicy(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::referrer, aValue, rv);
|
||||
SetHTMLAttr(nsGkAtoms::referrerpolicy, aValue, rv);
|
||||
}
|
||||
void GetReferrer(nsAString& aReferrer)
|
||||
void GetReferrerPolicy(nsAString& aReferrer)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::referrer, aReferrer);
|
||||
GetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer);
|
||||
}
|
||||
nsDOMTokenList* RelList();
|
||||
void GetHreflang(DOMString& aValue)
|
||||
|
||||
@@ -125,13 +125,13 @@ public:
|
||||
}
|
||||
nsDOMTokenList* RelList();
|
||||
|
||||
void SetReferrer(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
void SetReferrerPolicy(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::referrer, aValue, rv);
|
||||
SetHTMLAttr(nsGkAtoms::referrerpolicy, aValue, rv);
|
||||
}
|
||||
void GetReferrer(nsAString& aReferrer)
|
||||
void GetReferrerPolicy(nsAString& aReferrer)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::referrer, aReferrer);
|
||||
GetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer);
|
||||
}
|
||||
|
||||
// The Link::GetOrigin is OK for us
|
||||
|
||||
@@ -159,13 +159,13 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::marginheight, aMarginHeight, aError);
|
||||
}
|
||||
void SetReferrer(const nsAString& aReferrer, ErrorResult& aError)
|
||||
void SetReferrerPolicy(const nsAString& aReferrer, ErrorResult& aError)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::referrer, aReferrer, aError);
|
||||
SetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer, aError);
|
||||
}
|
||||
void GetReferrer(nsAString& aReferrer)
|
||||
void GetReferrerPolicy(nsAString& aReferrer)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::referrer, aReferrer);
|
||||
GetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer);
|
||||
}
|
||||
|
||||
nsIDocument* GetSVGDocument()
|
||||
|
||||
@@ -189,19 +189,19 @@ public:
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::border, aBorder, aError);
|
||||
}
|
||||
void SetReferrer(const nsAString& aReferrer, ErrorResult& aError)
|
||||
void SetReferrerPolicy(const nsAString& aReferrer, ErrorResult& aError)
|
||||
{
|
||||
SetHTMLAttr(nsGkAtoms::referrer, aReferrer, aError);
|
||||
SetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer, aError);
|
||||
}
|
||||
void GetReferrer(nsAString& aReferrer)
|
||||
void GetReferrerPolicy(nsAString& aReferrer)
|
||||
{
|
||||
GetHTMLAttr(nsGkAtoms::referrer, aReferrer);
|
||||
GetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer);
|
||||
}
|
||||
|
||||
net::ReferrerPolicy
|
||||
GetImageReferrerPolicy() override
|
||||
{
|
||||
return GetReferrerPolicy();
|
||||
return GetReferrerPolicyAsEnum();
|
||||
}
|
||||
|
||||
int32_t X();
|
||||
|
||||
@@ -29,6 +29,22 @@
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
#define LINK_ELEMENT_FLAG_BIT(n_) \
|
||||
NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
|
||||
// Link element specific bits
|
||||
enum {
|
||||
// Indicates that a DNS Prefetch has been requested from this Link element.
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED = LINK_ELEMENT_FLAG_BIT(0),
|
||||
|
||||
// Indicates that a DNS Prefetch was added to the deferral queue
|
||||
HTML_LINK_DNS_PREFETCH_DEFERRED = LINK_ELEMENT_FLAG_BIT(1)
|
||||
};
|
||||
|
||||
#undef LINK_ELEMENT_FLAG_BIT
|
||||
|
||||
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
|
||||
|
||||
NS_IMPL_NS_NEW_HTML_ELEMENT(Link)
|
||||
|
||||
namespace mozilla {
|
||||
@@ -127,6 +143,26 @@ HTMLLinkElement::SetItemValueText(const nsAString& aValue)
|
||||
SetHref(aValue);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLLinkElement::OnDNSPrefetchRequested()
|
||||
{
|
||||
UnsetFlags(HTML_LINK_DNS_PREFETCH_DEFERRED);
|
||||
SetFlags(HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLLinkElement::OnDNSPrefetchDeferred()
|
||||
{
|
||||
UnsetFlags(HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
SetFlags(HTML_LINK_DNS_PREFETCH_DEFERRED);
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLLinkElement::HasDeferredDNSPrefetchRequest()
|
||||
{
|
||||
return HasFlag(HTML_LINK_DNS_PREFETCH_DEFERRED);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
@@ -146,6 +182,9 @@ HTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
||||
if (IsInComposedDoc()) {
|
||||
UpdatePreconnect();
|
||||
if (HasDNSPrefetchRel()) {
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
}
|
||||
|
||||
void (HTMLLinkElement::*update)() = &HTMLLinkElement::UpdateStyleSheetInternal;
|
||||
@@ -174,6 +213,12 @@ HTMLLinkElement::LinkRemoved()
|
||||
void
|
||||
HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
{
|
||||
// Cancel any DNS prefetches
|
||||
// Note: Must come before ResetLinkState. If called after, it will recreate
|
||||
// mCachedURI based on data that is invalid - due to a call to GetHostname.
|
||||
CancelDNSPrefetch(HTML_LINK_DNS_PREFETCH_DEFERRED,
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
Link::ResetLinkState(false, Link::ElementHasHref());
|
||||
@@ -323,6 +368,32 @@ HTMLLinkElement::UpdatePreconnect()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLLinkElement::HasDNSPrefetchRel()
|
||||
{
|
||||
nsAutoString rel;
|
||||
if (GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
|
||||
return !!(ParseLinkTypes(rel, NodePrincipal()) &
|
||||
nsStyleLinkElement::eDNS_PREFETCH);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
nsAttrValueOrString* aValue, bool aNotify)
|
||||
{
|
||||
if (aNameSpaceID == kNameSpaceID_None &&
|
||||
(aName == nsGkAtoms::href || aName == nsGkAtoms::rel)) {
|
||||
CancelDNSPrefetch(HTML_LINK_DNS_PREFETCH_DEFERRED,
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
|
||||
aValue, aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue, bool aNotify)
|
||||
@@ -369,6 +440,11 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
}
|
||||
}
|
||||
|
||||
if ((aName == nsGkAtoms::rel || aName == nsGkAtoms::href) &&
|
||||
HasDNSPrefetchRel() && IsInComposedDoc()) {
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
|
||||
UpdateStyleSheetInternal(nullptr, nullptr,
|
||||
dropSheet ||
|
||||
(aName == nsGkAtoms::title ||
|
||||
|
||||
@@ -61,6 +61,9 @@ public:
|
||||
bool aCompileEventHandlers) override;
|
||||
virtual void UnbindFromTree(bool aDeep = true,
|
||||
bool aNullParent = true) override;
|
||||
virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
nsAttrValueOrString* aValue,
|
||||
bool aNotify) override;
|
||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
bool aNotify) override;
|
||||
@@ -77,6 +80,10 @@ public:
|
||||
|
||||
void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
|
||||
|
||||
virtual void OnDNSPrefetchDeferred() override;
|
||||
virtual void OnDNSPrefetchRequested() override;
|
||||
virtual bool HasDeferredDNSPrefetchRequest() override;
|
||||
|
||||
// WebIDL
|
||||
bool Disabled();
|
||||
void SetDisabled(bool aDisabled);
|
||||
@@ -166,6 +173,9 @@ protected:
|
||||
// nsGenericHTMLElement
|
||||
virtual void GetItemValueText(DOMString& text) override;
|
||||
virtual void SetItemValueText(const nsAString& text) override;
|
||||
|
||||
bool HasDNSPrefetchRel();
|
||||
|
||||
RefPtr<nsDOMTokenList > mRelList;
|
||||
private:
|
||||
RefPtr<ImportLoader> mImportLoader;
|
||||
|
||||
@@ -563,12 +563,18 @@ nsBrowserElement::GetAllowedAudioChannels(
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIApplication> parentApp;
|
||||
aRv = GetParentApplication(getter_AddRefs(parentApp));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug,
|
||||
("nsBrowserElement, GetAllowedAudioChannels, this = %p\n", this));
|
||||
|
||||
GenerateAllowedAudioChannels(window, frameLoader, mBrowserElementAPI,
|
||||
manifestURL, mBrowserElementAudioChannels,
|
||||
aRv);
|
||||
manifestURL, parentApp,
|
||||
mBrowserElementAudioChannels, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
@@ -583,6 +589,7 @@ nsBrowserElement::GenerateAllowedAudioChannels(
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
const nsAString& aManifestURL,
|
||||
mozIApplication* aParentApp,
|
||||
nsTArray<RefPtr<BrowserElementAudioChannel>>& aAudioChannels,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
@@ -625,6 +632,19 @@ nsBrowserElement::GenerateAllowedAudioChannels(
|
||||
permissionName.AssignASCII("audio-channel-");
|
||||
permissionName.AppendASCII(audioChannelTable[i].tag);
|
||||
|
||||
// In case of nested iframes we want to check if the parent has the
|
||||
// permission to use this AudioChannel.
|
||||
if (aParentApp) {
|
||||
aRv = aParentApp->HasPermission(permissionName.get(), &allowed);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!allowed) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
aRv = app->HasPermission(permissionName.get(), &allowed);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
|
||||
@@ -125,11 +125,14 @@ public:
|
||||
nsIFrameLoader* aFrameLoader,
|
||||
nsIBrowserElementAPI* aAPI,
|
||||
const nsAString& aManifestURL,
|
||||
mozIApplication* aParentApp,
|
||||
nsTArray<RefPtr<dom::BrowserElementAudioChannel>>& aAudioChannels,
|
||||
ErrorResult& aRv);
|
||||
|
||||
protected:
|
||||
NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() = 0;
|
||||
NS_IMETHOD GetParentApplication(mozIApplication** aApplication) = 0;
|
||||
|
||||
void InitBrowserElementAPI();
|
||||
nsCOMPtr<nsIBrowserElementAPI> mBrowserElementAPI;
|
||||
nsTArray<RefPtr<dom::BrowserElementAudioChannel>> mBrowserElementAudioChannels;
|
||||
|
||||
@@ -1003,7 +1003,7 @@ nsGenericHTMLElement::ParseAttribute(int32_t aNamespaceID,
|
||||
return aResult.ParseIntValue(aValue);
|
||||
}
|
||||
|
||||
if (aAttribute == nsGkAtoms::referrer) {
|
||||
if (aAttribute == nsGkAtoms::referrerpolicy) {
|
||||
return ParseReferrerAttribute(aValue, aResult);
|
||||
}
|
||||
|
||||
|
||||
@@ -188,6 +188,35 @@ nsGenericHTMLFrameElement::GetFrameLoader()
|
||||
return loader.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericHTMLFrameElement::GetParentApplication(mozIApplication** aApplication)
|
||||
{
|
||||
if (!aApplication) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aApplication = nullptr;
|
||||
|
||||
uint32_t appId;
|
||||
nsIPrincipal *principal = NodePrincipal();
|
||||
nsresult rv = principal->GetAppId(&appId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (NS_WARN_IF(!appsService)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = appsService->GetAppByLocalId(appId, aApplication);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGenericHTMLFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(7615408c-1fb3-4128-8dd5-a3e2f3fa8842)]
|
||||
[builtinclass, scriptable, uuid(8e49f7b0-1f98-4939-bf91-e9c39cd56434)]
|
||||
interface nsITabParent : nsISupports
|
||||
{
|
||||
void injectTouchEvent(in AString aType,
|
||||
|
||||
+18
-13
@@ -235,20 +235,19 @@ parent:
|
||||
IMENotification notification);
|
||||
|
||||
/**
|
||||
* Instructs chrome to end any pending composition
|
||||
* Requests chrome to commit or cancel composition of IME.
|
||||
*
|
||||
* cancel true if composition should be cancelled
|
||||
* noCompositionEvent true if no composition event is fired by commit or
|
||||
* cancel
|
||||
* composition Text to commit before ending the composition
|
||||
* cancel Set true if composition should be cancelled.
|
||||
*
|
||||
* if cancel is true,
|
||||
* widget should return empty string for composition
|
||||
* if cancel is false,
|
||||
* widget should return the current composition text
|
||||
* isCommitted Returns true if the request causes composition
|
||||
* being committed synchronously.
|
||||
* committedString Returns committed string. The may be non-empty
|
||||
* string even if cancel is true because IME may
|
||||
* try to restore selected string which was
|
||||
* replaced with the composition.
|
||||
*/
|
||||
prio(urgent) sync EndIMEComposition(bool cancel)
|
||||
returns (bool noCompositionEvent, nsString composition);
|
||||
prio(urgent) sync RequestIMEToCommitComposition(bool cancel)
|
||||
returns (bool isCommitted, nsString committedString);
|
||||
|
||||
/**
|
||||
* OnEventNeedingAckHandled() is called after a child process dispatches a
|
||||
@@ -296,8 +295,7 @@ parent:
|
||||
nsCString[] disabledCommands);
|
||||
|
||||
prio(urgent) sync GetInputContext() returns (int32_t IMEEnabled,
|
||||
int32_t IMEOpen,
|
||||
intptr_t NativeIMEContext);
|
||||
int32_t IMEOpen);
|
||||
|
||||
prio(urgent) async SetInputContext(int32_t IMEEnabled,
|
||||
int32_t IMEOpen,
|
||||
@@ -748,6 +746,13 @@ child:
|
||||
*/
|
||||
HandleAccessKey(uint32_t[] charCodes, bool isTrusted, int32_t modifierMask);
|
||||
|
||||
/**
|
||||
* Propagate a refresh to the child process
|
||||
*/
|
||||
AudioChannelChangeNotification(uint32_t aAudioChannel,
|
||||
float aVolume,
|
||||
bool aMuted);
|
||||
|
||||
/*
|
||||
* FIXME: write protocol!
|
||||
|
||||
|
||||
@@ -2212,6 +2212,27 @@ TabChild::RecvHandleAccessKey(nsTArray<uint32_t>&& aCharCodes,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvAudioChannelChangeNotification(const uint32_t& aAudioChannel,
|
||||
const float& aVolume,
|
||||
const bool& aMuted)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
|
||||
if (window) {
|
||||
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||
MOZ_ASSERT(service);
|
||||
|
||||
service->SetAudioChannelVolume(window,
|
||||
static_cast<AudioChannel>(aAudioChannel),
|
||||
aVolume);
|
||||
service->SetAudioChannelMuted(window,
|
||||
static_cast<AudioChannel>(aAudioChannel),
|
||||
aMuted);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvDestroy()
|
||||
{
|
||||
|
||||
@@ -501,6 +501,10 @@ public:
|
||||
const bool& aIsTrusted,
|
||||
const int32_t& aModifierMask) override;
|
||||
|
||||
virtual bool RecvAudioChannelChangeNotification(const uint32_t& aAudioChannel,
|
||||
const float& aVolume,
|
||||
const bool& aMuted) override;
|
||||
|
||||
/**
|
||||
* Native widget remoting protocol for use with windowed plugins with e10s.
|
||||
*/
|
||||
|
||||
+48
-12
@@ -183,7 +183,7 @@ private:
|
||||
// Our TabParent may have been destroyed already. If so, don't send any
|
||||
// fds over, just go back to the IO thread and close them.
|
||||
if (!tabParent->IsDestroyed()) {
|
||||
mozilla::Unused << tabParent->SendCacheFileDescriptor(mPath, fd);
|
||||
Unused << tabParent->SendCacheFileDescriptor(mPath, fd);
|
||||
}
|
||||
|
||||
if (!mFD) {
|
||||
@@ -231,7 +231,7 @@ private:
|
||||
// Intentionally leak the runnable (but not the fd) rather
|
||||
// than crash when trying to release a main thread object
|
||||
// off the main thread.
|
||||
mozilla::Unused << mTabParent.forget();
|
||||
Unused << mTabParent.forget();
|
||||
CloseFile();
|
||||
}
|
||||
}
|
||||
@@ -384,6 +384,11 @@ TabParent::AddWindowListeners()
|
||||
mPresShellWithRefreshListener = shell;
|
||||
shell->AddPostRefreshObserver(this);
|
||||
}
|
||||
|
||||
RefPtr<AudioChannelService> acs = AudioChannelService::GetOrCreate();
|
||||
if (acs) {
|
||||
acs->RegisterTabParent(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,6 +407,11 @@ TabParent::RemoveWindowListeners()
|
||||
mPresShellWithRefreshListener->RemovePostRefreshObserver(this);
|
||||
mPresShellWithRefreshListener = nullptr;
|
||||
}
|
||||
|
||||
RefPtr<AudioChannelService> acs = AudioChannelService::GetOrCreate();
|
||||
if (acs) {
|
||||
acs->UnregisterTabParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2319,16 +2329,19 @@ TabParent::GetRenderFrame()
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvEndIMEComposition(const bool& aCancel,
|
||||
bool* aNoCompositionEvent,
|
||||
nsString* aComposition)
|
||||
TabParent::RecvRequestIMEToCommitComposition(const bool& aCancel,
|
||||
bool* aIsCommitted,
|
||||
nsString* aCommittedString)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget) {
|
||||
*aIsCommitted = false;
|
||||
return true;
|
||||
}
|
||||
*aNoCompositionEvent =
|
||||
!mContentCache.RequestToCommitComposition(widget, aCancel, *aComposition);
|
||||
|
||||
*aIsCommitted =
|
||||
mContentCache.RequestIMEToCommitComposition(widget, aCancel,
|
||||
*aCommittedString);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2361,21 +2374,18 @@ TabParent::RecvSetPluginFocused(const bool& aFocused)
|
||||
|
||||
bool
|
||||
TabParent::RecvGetInputContext(int32_t* aIMEEnabled,
|
||||
int32_t* aIMEOpen,
|
||||
intptr_t* aNativeIMEContext)
|
||||
int32_t* aIMEOpen)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget) {
|
||||
*aIMEEnabled = IMEState::DISABLED;
|
||||
*aIMEOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
|
||||
*aNativeIMEContext = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
InputContext context = widget->GetInputContext();
|
||||
*aIMEEnabled = static_cast<int32_t>(context.mIMEState.mEnabled);
|
||||
*aIMEOpen = static_cast<int32_t>(context.mIMEState.mOpen);
|
||||
*aNativeIMEContext = reinterpret_cast<intptr_t>(context.mNativeIMEContext);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2634,7 +2644,6 @@ TabParent::RecvAudioChannelActivityNotification(const uint32_t& aAudioChannel,
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||
if (os) {
|
||||
RefPtr<AudioChannelService> service = AudioChannelService::GetOrCreate();
|
||||
nsAutoCString topic;
|
||||
topic.Assign("audiochannel-activity-");
|
||||
topic.Append(AudioChannelService::GetAudioChannelTable()[aAudioChannel].tag);
|
||||
@@ -3371,6 +3380,33 @@ TabParent::GetShowInfo()
|
||||
mDPI, mDefaultScale.scale);
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::AudioChannelChangeNotification(nsPIDOMWindow* aWindow,
|
||||
AudioChannel aAudioChannel,
|
||||
float aVolume,
|
||||
bool aMuted)
|
||||
{
|
||||
if (!mFrameElement || !mFrameElement->OwnerDoc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = mFrameElement->OwnerDoc()->GetWindow();
|
||||
while (window) {
|
||||
if (window == aWindow) {
|
||||
Unused << SendAudioChannelChangeNotification(static_cast<uint32_t>(aAudioChannel),
|
||||
aVolume, aMuted);
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> win = window->GetScriptableParent();
|
||||
if (window == win) {
|
||||
break;
|
||||
}
|
||||
|
||||
window = win;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
|
||||
{
|
||||
|
||||
+10
-5
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/ContentCache.h"
|
||||
#include "mozilla/dom/AudioChannelBinding.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
#include "mozilla/dom/PBrowserParent.h"
|
||||
#include "mozilla/dom/PContent.h"
|
||||
@@ -185,17 +186,16 @@ public:
|
||||
virtual bool RecvNotifyIMEPositionChange(const ContentCache& aContentCache,
|
||||
const widget::IMENotification& aEventMessage) override;
|
||||
virtual bool RecvOnEventNeedingAckHandled(const EventMessage& aMessage) override;
|
||||
virtual bool RecvEndIMEComposition(const bool& aCancel,
|
||||
bool* aNoCompositionEvent,
|
||||
nsString* aComposition) override;
|
||||
virtual bool RecvRequestIMEToCommitComposition(const bool& aCancel,
|
||||
bool* aIsCommitted,
|
||||
nsString* aCommittedString) override;
|
||||
virtual bool RecvStartPluginIME(const WidgetKeyboardEvent& aKeyboardEvent,
|
||||
const int32_t& aPanelX,
|
||||
const int32_t& aPanelY,
|
||||
nsString* aCommitted) override;
|
||||
virtual bool RecvSetPluginFocused(const bool& aFocused) override;
|
||||
virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
|
||||
int32_t* aIMEOpen,
|
||||
intptr_t* aNativeIMEContext) override;
|
||||
int32_t* aIMEOpen) override;
|
||||
virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
|
||||
const int32_t& aIMEOpen,
|
||||
const nsString& aType,
|
||||
@@ -453,6 +453,11 @@ public:
|
||||
void OnStartSignedPackageRequest(nsIChannel* aChannel,
|
||||
const nsACString& aPackageId);
|
||||
|
||||
void AudioChannelChangeNotification(nsPIDOMWindow* aWindow,
|
||||
AudioChannel aAudioChannel,
|
||||
float aVolume,
|
||||
bool aMuted);
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
|
||||
@@ -213,8 +213,8 @@ AudioChannelManager::GetAllowedAudioChannels(
|
||||
}
|
||||
|
||||
nsBrowserElement::GenerateAllowedAudioChannels(window, nullptr, nullptr,
|
||||
manifestURL, aAudioChannels,
|
||||
aRv);
|
||||
manifestURL, nullptr,
|
||||
aAudioChannels, aRv);
|
||||
NS_WARN_IF(aRv.Failed());
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ interface Element : Node {
|
||||
[SameObject]
|
||||
readonly attribute NamedNodeMap attributes;
|
||||
[Pure]
|
||||
sequence<DOMString> getAttributeNames();
|
||||
[Pure]
|
||||
DOMString? getAttribute(DOMString name);
|
||||
[Pure]
|
||||
DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
|
||||
@@ -61,6 +63,8 @@ interface Element : Node {
|
||||
|
||||
[Throws, Pure]
|
||||
boolean matches(DOMString selector);
|
||||
[Throws, Pure, BinaryName="matches"]
|
||||
boolean webkitMatchesSelector(DOMString selector);
|
||||
|
||||
[Pure]
|
||||
HTMLCollection getElementsByTagName(DOMString localName);
|
||||
@@ -100,7 +104,7 @@ interface Element : Node {
|
||||
*
|
||||
* See <http://dev.w3.org/2006/webapi/selectors-api2/#matchesselector>
|
||||
*/
|
||||
[Throws, Pure]
|
||||
[Throws, Pure, BinaryName="matches"]
|
||||
boolean mozMatchesSelector(DOMString selector);
|
||||
|
||||
// Pointer events methods.
|
||||
|
||||
@@ -22,7 +22,7 @@ interface HTMLAnchorElement : HTMLElement {
|
||||
[SetterThrows]
|
||||
attribute DOMString rel;
|
||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrer;
|
||||
attribute DOMString referrerPolicy;
|
||||
readonly attribute DOMTokenList relList;
|
||||
[SetterThrows]
|
||||
attribute DOMString hreflang;
|
||||
|
||||
@@ -29,7 +29,7 @@ interface HTMLAreaElement : HTMLElement {
|
||||
[SetterThrows]
|
||||
attribute DOMString rel;
|
||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrer;
|
||||
attribute DOMString referrerPolicy;
|
||||
readonly attribute DOMTokenList relList;
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ interface HTMLIFrameElement : HTMLElement {
|
||||
[SetterThrows, Pure]
|
||||
attribute DOMString height;
|
||||
[SetterThrows, Pure, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrer;
|
||||
attribute DOMString referrerPolicy;
|
||||
readonly attribute Document? contentDocument;
|
||||
readonly attribute WindowProxy? contentWindow;
|
||||
};
|
||||
|
||||
@@ -29,8 +29,8 @@ interface HTMLImageElement : HTMLElement {
|
||||
attribute DOMString? crossOrigin;
|
||||
[SetterThrows]
|
||||
attribute DOMString useMap;
|
||||
[SetterThrows]
|
||||
attribute DOMString referrer;
|
||||
[SetterThrows, Pref="network.http.enablePerElementReferrer"]
|
||||
attribute DOMString referrerPolicy;
|
||||
[SetterThrows]
|
||||
attribute boolean isMap;
|
||||
[SetterThrows]
|
||||
|
||||
@@ -617,13 +617,6 @@ nsXMLContentSink::CloseElement(nsIContent* aContent)
|
||||
PrefetchHref(hrefVal, aContent, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1612,6 +1612,17 @@ nsXULElement::GetFrameLoader()
|
||||
return loader.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULElement::GetParentApplication(mozIApplication** aApplication)
|
||||
{
|
||||
if (!aApplication) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aApplication = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULElement::SetIsPrerendered()
|
||||
{
|
||||
|
||||
@@ -437,6 +437,7 @@ public:
|
||||
virtual mozilla::EventStates IntrinsicState() const override;
|
||||
|
||||
nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader);
|
||||
nsresult GetParentApplication(mozIApplication** aApplication);
|
||||
nsresult SetIsPrerendered();
|
||||
nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner);
|
||||
|
||||
|
||||
@@ -1993,14 +1993,14 @@ nsEditor::StopPreservingSelection()
|
||||
}
|
||||
|
||||
void
|
||||
nsEditor::EnsureComposition(mozilla::WidgetGUIEvent* aEvent)
|
||||
nsEditor::EnsureComposition(mozilla::WidgetCompositionEvent* aCompositionEvent)
|
||||
{
|
||||
if (mComposition) {
|
||||
return;
|
||||
}
|
||||
// The compositionstart event must cause creating new TextComposition
|
||||
// instance at being dispatched by IMEStateManager.
|
||||
mComposition = IMEStateManager::GetTextCompositionFor(aEvent);
|
||||
mComposition = IMEStateManager::GetTextCompositionFor(aCompositionEvent);
|
||||
if (!mComposition) {
|
||||
MOZ_CRASH("IMEStateManager doesn't return proper composition");
|
||||
}
|
||||
|
||||
@@ -413,7 +413,7 @@ protected:
|
||||
* EnsureComposition() should be called by composition event handlers. This
|
||||
* tries to get the composition for the event and set it to mComposition.
|
||||
*/
|
||||
void EnsureComposition(mozilla::WidgetGUIEvent* aEvent);
|
||||
void EnsureComposition(mozilla::WidgetCompositionEvent* aCompositionEvent);
|
||||
|
||||
nsresult GetSelection(int16_t aSelectionType, nsISelection** aSelection);
|
||||
|
||||
|
||||
@@ -1286,12 +1286,11 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
Rect frameGfxRect = NSRectToRect(frameRect, twipsPerPixel);
|
||||
frameGfxRect.Round();
|
||||
|
||||
// We don't show anything that intersects with the frame we're blurring on. So tell the
|
||||
// blurrer not to do unnecessary work there.
|
||||
gfxRect skipGfxRect = ThebesRect(frameGfxRect);
|
||||
gfxRect skipGfxRect = ThebesRect(NSRectToRect(frameRect, twipsPerPixel));
|
||||
skipGfxRect.Round();
|
||||
bool useSkipGfxRect = true;
|
||||
if (nativeTheme) {
|
||||
// Optimize non-leaf native-themed frames by skipping computing pixels
|
||||
@@ -1394,15 +1393,20 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
renderContext->Save();
|
||||
|
||||
{
|
||||
Rect innerClipRect = NSRectToRect(frameRect, twipsPerPixel);
|
||||
if (!MaybeSnapToDevicePixels(innerClipRect, aDrawTarget, true)) {
|
||||
innerClipRect.Round();
|
||||
}
|
||||
|
||||
// Clip out the interior of the frame's border edge so that the shadow
|
||||
// is only painted outside that area.
|
||||
RefPtr<PathBuilder> builder =
|
||||
aDrawTarget.CreatePathBuilder(FillRule::FILL_EVEN_ODD);
|
||||
AppendRectToPath(builder, shadowGfxRectPlusBlur);
|
||||
if (hasBorderRadius) {
|
||||
AppendRoundedRectToPath(builder, frameGfxRect, borderRadii);
|
||||
AppendRoundedRectToPath(builder, innerClipRect, borderRadii);
|
||||
} else {
|
||||
AppendRectToPath(builder, frameGfxRect);
|
||||
AppendRectToPath(builder, innerClipRect);
|
||||
}
|
||||
RefPtr<Path> path = builder->Finish();
|
||||
renderContext->Clip(path);
|
||||
|
||||
@@ -386,6 +386,26 @@ nsAnimationManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
nsAnimationManager::CopyIsRunningOnCompositor(
|
||||
KeyframeEffectReadOnly& aSourceEffect,
|
||||
KeyframeEffectReadOnly& aDestEffect)
|
||||
{
|
||||
nsCSSPropertySet sourceProperties;
|
||||
|
||||
for (AnimationProperty& property : aSourceEffect.Properties()) {
|
||||
if (property.mIsRunningOnCompositor) {
|
||||
sourceProperties.AddProperty(property.mProperty);
|
||||
}
|
||||
}
|
||||
|
||||
for (AnimationProperty& property : aDestEffect.Properties()) {
|
||||
if (sourceProperties.HasProperty(property.mProperty)) {
|
||||
property.mIsRunningOnCompositor = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsIStyleRule*
|
||||
nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
|
||||
mozilla::dom::Element* aElement)
|
||||
@@ -493,6 +513,12 @@ nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
|
||||
oldEffect->Timing() != newEffect->Timing() ||
|
||||
oldEffect->Properties() != newEffect->Properties();
|
||||
oldEffect->SetTiming(newEffect->Timing());
|
||||
|
||||
// To preserve the mIsRunningOnCompositor value on each property,
|
||||
// we copy it from the old effect to the new effect since, in the
|
||||
// following step, we will completely clobber the properties on the
|
||||
// old effect with the values on the new effect.
|
||||
CopyIsRunningOnCompositor(*oldEffect, *newEffect);
|
||||
oldEffect->Properties() = newEffect->Properties();
|
||||
}
|
||||
|
||||
@@ -789,7 +815,6 @@ nsAnimationManager::BuildAnimations(nsStyleContext* aStyleContext,
|
||||
|
||||
AnimationProperty &propData = *destEffect->Properties().AppendElement();
|
||||
propData.mProperty = prop;
|
||||
propData.mWinsInCascade = true;
|
||||
|
||||
KeyframeData *fromKeyframe = nullptr;
|
||||
RefPtr<nsStyleContext> fromContext;
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace css {
|
||||
class Declaration;
|
||||
} /* namespace css */
|
||||
namespace dom {
|
||||
class KeyframeEffectReadOnly;
|
||||
class Promise;
|
||||
} /* namespace dom */
|
||||
|
||||
@@ -373,6 +374,9 @@ private:
|
||||
static void UpdateCascadeResults(nsStyleContext* aStyleContext,
|
||||
mozilla::AnimationCollection*
|
||||
aElementAnimations);
|
||||
static void CopyIsRunningOnCompositor(
|
||||
mozilla::dom::KeyframeEffectReadOnly& aSourceEffect,
|
||||
mozilla::dom::KeyframeEffectReadOnly& aDestEffect);
|
||||
};
|
||||
|
||||
#endif /* !defined(nsAnimationManager_h_) */
|
||||
|
||||
@@ -679,7 +679,6 @@ nsTransitionManager::ConsiderStartingTransition(
|
||||
|
||||
AnimationProperty& prop = *pt->Properties().AppendElement();
|
||||
prop.mProperty = aProperty;
|
||||
prop.mWinsInCascade = true;
|
||||
|
||||
AnimationPropertySegment& segment = *prop.mSegments.AppendElement();
|
||||
segment.mFromValue = startValue;
|
||||
|
||||
@@ -153,13 +153,18 @@ static void anp_drawBitmapRect(ANPCanvas* canvas, const ANPBitmap* bitmap,
|
||||
const ANPPaint* paint) {
|
||||
SkBitmap bm;
|
||||
SkRect dstR;
|
||||
SkIRect srcR, *srcPtr = NULL;
|
||||
SkIRect srcR;
|
||||
|
||||
if (src) {
|
||||
srcPtr = SkANP::SetRect(&srcR, *src);
|
||||
canvas->skcanvas->drawBitmapRect(*SkANP::SetBitmap(&bm, *bitmap),
|
||||
*SkANP::SetRect(&srcR, *src),
|
||||
*SkANP::SetRect(&dstR, *dst),
|
||||
paint);
|
||||
} else {
|
||||
canvas->skcanvas->drawBitmapRect(*SkANP::SetBitmap(&bm, *bitmap),
|
||||
*SkANP::SetRect(&dstR, *dst),
|
||||
paint);
|
||||
}
|
||||
canvas->skcanvas->drawBitmapRect(*SkANP::SetBitmap(&bm, *bitmap), srcPtr,
|
||||
*SkANP::SetRect(&dstR, *dst), paint);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "SkANP.h"
|
||||
#include "SkFontHost.h"
|
||||
#include "SkStream.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static ANPTypeface* anp_createFromName(const char name[], ANPTypefaceStyle s) {
|
||||
SkTypeface* tf = SkTypeface::CreateFromName(name,
|
||||
|
||||
@@ -545,7 +545,7 @@ public final class AttributeName
|
||||
// builder.append(" | ");
|
||||
// }
|
||||
// builder.append("NCNAME_HTML");
|
||||
// }
|
||||
// }
|
||||
// if ((flags & NCNAME_FOREIGN) != 0) {
|
||||
// if (builder.length() != 0) {
|
||||
// builder.append(" | ");
|
||||
@@ -683,7 +683,7 @@ public final class AttributeName
|
||||
//
|
||||
// /**
|
||||
// * Regenerate self
|
||||
// *
|
||||
// *
|
||||
// * @param args
|
||||
// */
|
||||
// public static void main(String[] args) {
|
||||
@@ -990,7 +990,6 @@ public final class AttributeName
|
||||
public static final AttributeName READONLY = new AttributeName(ALL_NO_NS, SAME_LOCAL("readonly"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
|
||||
public static final AttributeName SELECTED = new AttributeName(ALL_NO_NS, SAME_LOCAL("selected"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG | CASE_FOLDED | BOOLEAN);
|
||||
public static final AttributeName ROWLINES = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowlines"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName REFERRER = new AttributeName(ALL_NO_NS, SAME_LOCAL("referrer"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName SEAMLESS = new AttributeName(ALL_NO_NS, SAME_LOCAL("seamless"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName ROWALIGN = new AttributeName(ALL_NO_NS, SAME_LOCAL("rowalign"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName STRETCHY = new AttributeName(ALL_NO_NS, SAME_LOCAL("stretchy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
@@ -1234,6 +1233,7 @@ public final class AttributeName
|
||||
public static final AttributeName V_MATHEMATICAL = new AttributeName(ALL_NO_NS, SAME_LOCAL("v-mathematical"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName POINTER_EVENTS = new AttributeName(ALL_NO_NS, SAME_LOCAL("pointer-events"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName PRIMITIVEUNITS = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("primitiveunits", "primitiveUnits"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName REFERRERPOLICY = new AttributeName(ALL_NO_NS, SAME_LOCAL("referrerpolicy"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName SYSTEMLANGUAGE = new AttributeName(ALL_NO_NS, SVG_DIFFERENT("systemlanguage", "systemLanguage"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName STROKE_LINECAP = new AttributeName(ALL_NO_NS, SAME_LOCAL("stroke-linecap"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
public static final AttributeName SUBSCRIPTSHIFT = new AttributeName(ALL_NO_NS, SAME_LOCAL("subscriptshift"), ALL_NO_PREFIX, NCNAME_HTML | NCNAME_FOREIGN | NCNAME_LANG);
|
||||
@@ -1574,7 +1574,6 @@ public final class AttributeName
|
||||
READONLY,
|
||||
SELECTED,
|
||||
ROWLINES,
|
||||
REFERRER,
|
||||
SEAMLESS,
|
||||
ROWALIGN,
|
||||
STRETCHY,
|
||||
@@ -1818,6 +1817,7 @@ public final class AttributeName
|
||||
V_MATHEMATICAL,
|
||||
POINTER_EVENTS,
|
||||
PRIMITIVEUNITS,
|
||||
REFERRERPOLICY,
|
||||
SYSTEMLANGUAGE,
|
||||
STROKE_LINECAP,
|
||||
SUBSCRIPTSHIFT,
|
||||
@@ -2159,7 +2159,6 @@ public final class AttributeName
|
||||
291557706,
|
||||
291665349,
|
||||
291804100,
|
||||
291862420,
|
||||
292138018,
|
||||
292166446,
|
||||
292418738,
|
||||
@@ -2403,6 +2402,7 @@ public final class AttributeName
|
||||
490661867,
|
||||
491574090,
|
||||
491578272,
|
||||
492891370,
|
||||
493041952,
|
||||
493441205,
|
||||
493582844,
|
||||
|
||||
@@ -349,7 +349,6 @@ HTML5_ATOM(property, "property")
|
||||
HTML5_ATOM(readonly, "readonly")
|
||||
HTML5_ATOM(selected, "selected")
|
||||
HTML5_ATOM(rowlines, "rowlines")
|
||||
HTML5_ATOM(referrer, "referrer")
|
||||
HTML5_ATOM(seamless, "seamless")
|
||||
HTML5_ATOM(rowalign, "rowalign")
|
||||
HTML5_ATOM(stretchy, "stretchy")
|
||||
@@ -632,6 +631,7 @@ HTML5_ATOM(v_mathematical, "v-mathematical")
|
||||
HTML5_ATOM(pointer_events, "pointer-events")
|
||||
HTML5_ATOM(primitiveunits, "primitiveunits")
|
||||
HTML5_ATOM(primitiveUnits, "primitiveUnits")
|
||||
HTML5_ATOM(referrerpolicy, "referrerpolicy")
|
||||
HTML5_ATOM(systemlanguage, "systemlanguage")
|
||||
HTML5_ATOM(systemLanguage, "systemLanguage")
|
||||
HTML5_ATOM(stroke_linecap, "stroke-linecap")
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -365,7 +365,6 @@ class nsHtml5AttributeName
|
||||
static nsHtml5AttributeName* ATTR_READONLY;
|
||||
static nsHtml5AttributeName* ATTR_SELECTED;
|
||||
static nsHtml5AttributeName* ATTR_ROWLINES;
|
||||
static nsHtml5AttributeName* ATTR_REFERRER;
|
||||
static nsHtml5AttributeName* ATTR_SEAMLESS;
|
||||
static nsHtml5AttributeName* ATTR_ROWALIGN;
|
||||
static nsHtml5AttributeName* ATTR_STRETCHY;
|
||||
@@ -609,6 +608,7 @@ class nsHtml5AttributeName
|
||||
static nsHtml5AttributeName* ATTR_V_MATHEMATICAL;
|
||||
static nsHtml5AttributeName* ATTR_POINTER_EVENTS;
|
||||
static nsHtml5AttributeName* ATTR_PRIMITIVEUNITS;
|
||||
static nsHtml5AttributeName* ATTR_REFERRERPOLICY;
|
||||
static nsHtml5AttributeName* ATTR_SYSTEMLANGUAGE;
|
||||
static nsHtml5AttributeName* ATTR_STROKE_LINECAP;
|
||||
static nsHtml5AttributeName* ATTR_SUBSCRIPTSHIFT;
|
||||
|
||||
@@ -96,13 +96,6 @@ nsHtml5DocumentBuilder::UpdateStyleSheet(nsIContent* aElement)
|
||||
PrefetchHref(hrefVal, aElement, hasPrefetch);
|
||||
}
|
||||
}
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
nsAutoString hrefVal;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
|
||||
if (!hrefVal.IsEmpty()) {
|
||||
PrefetchDNS(hrefVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ nsHtml5Highlighter::nsHtml5Highlighter(nsAHtml5TreeOpSink* aOpSink)
|
||||
, mCurrentRun(nullptr)
|
||||
, mAmpersand(nullptr)
|
||||
, mSlash(nullptr)
|
||||
, mHandles(new nsIContent*[NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH])
|
||||
, mHandles(MakeUnique<nsIContent*[]>(NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH))
|
||||
, mHandlesUsed(0)
|
||||
, mSeenBase(false)
|
||||
{
|
||||
@@ -641,8 +641,8 @@ nsIContent**
|
||||
nsHtml5Highlighter::AllocateContentHandle()
|
||||
{
|
||||
if (mHandlesUsed == NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH) {
|
||||
mOldHandles.AppendElement(mHandles.forget());
|
||||
mHandles = new nsIContent*[NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH];
|
||||
mOldHandles.AppendElement(Move(mHandles));
|
||||
mHandles = MakeUnique<nsIContent*[]>(NS_HTML5_HIGHLIGHTER_HANDLE_ARRAY_LENGTH);
|
||||
mHandlesUsed = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -342,7 +342,7 @@ class nsHtml5Highlighter
|
||||
/**
|
||||
* Memory for element handles.
|
||||
*/
|
||||
nsAutoArrayPtr<nsIContent*> mHandles;
|
||||
mozilla::UniquePtr<nsIContent*[]> mHandles;
|
||||
|
||||
/**
|
||||
* Number of handles used in mHandles
|
||||
@@ -352,7 +352,7 @@ class nsHtml5Highlighter
|
||||
/**
|
||||
* A holder for old contents of mHandles
|
||||
*/
|
||||
nsTArray<nsAutoArrayPtr<nsIContent*> > mOldHandles;
|
||||
nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles;
|
||||
|
||||
/**
|
||||
* The element stack.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "nsHtml5RefPtr.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "nsHtml5Highlighter.h"
|
||||
#include "expat_config.h"
|
||||
#include "expat.h"
|
||||
@@ -300,7 +301,7 @@ nsHtml5StreamParser::SetupDecodingAndWriteSniffingBufferAndCurrentSegment(const
|
||||
mUnicodeDecoder = EncodingUtils::DecoderForEncoding(mCharset);
|
||||
if (mSniffingBuffer) {
|
||||
uint32_t writeCount;
|
||||
rv = WriteStreamBytes(mSniffingBuffer, mSniffingLength, &writeCount);
|
||||
rv = WriteStreamBytes(mSniffingBuffer.get(), mSniffingLength, &writeCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mSniffingBuffer = nullptr;
|
||||
}
|
||||
@@ -783,13 +784,13 @@ nsHtml5StreamParser::SniffStreamBytes(const uint8_t* aFromSegment,
|
||||
}
|
||||
|
||||
if (!mSniffingBuffer) {
|
||||
mSniffingBuffer = new (mozilla::fallible)
|
||||
uint8_t[NS_HTML5_STREAM_PARSER_SNIFFING_BUFFER_SIZE];
|
||||
mSniffingBuffer =
|
||||
MakeUniqueFallible<uint8_t[]>(NS_HTML5_STREAM_PARSER_SNIFFING_BUFFER_SIZE);
|
||||
if (!mSniffingBuffer) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
memcpy(mSniffingBuffer + mSniffingLength, aFromSegment, aCount);
|
||||
memcpy(&mSniffingBuffer[mSniffingLength], aFromSegment, aCount);
|
||||
mSniffingLength += aCount;
|
||||
*aWriteCount = aCount;
|
||||
return NS_OK;
|
||||
@@ -1126,20 +1127,20 @@ class nsHtml5DataAvailable : public nsRunnable
|
||||
{
|
||||
private:
|
||||
nsHtml5RefPtr<nsHtml5StreamParser> mStreamParser;
|
||||
nsAutoArrayPtr<uint8_t> mData;
|
||||
UniquePtr<uint8_t[]> mData;
|
||||
uint32_t mLength;
|
||||
public:
|
||||
nsHtml5DataAvailable(nsHtml5StreamParser* aStreamParser,
|
||||
uint8_t* aData,
|
||||
UniquePtr<uint8_t[]> aData,
|
||||
uint32_t aLength)
|
||||
: mStreamParser(aStreamParser)
|
||||
, mData(aData)
|
||||
, mData(Move(aData))
|
||||
, mLength(aLength)
|
||||
{}
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
mozilla::MutexAutoLock autoLock(mStreamParser->mTokenizerMutex);
|
||||
mStreamParser->DoDataAvailable(mData, mLength);
|
||||
mStreamParser->DoDataAvailable(mData.get(), mLength);
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
@@ -1160,7 +1161,7 @@ nsHtml5StreamParser::OnDataAvailable(nsIRequest* aRequest,
|
||||
uint32_t totalRead;
|
||||
// Main thread to parser thread dispatch requires copying to buffer first.
|
||||
if (NS_IsMainThread()) {
|
||||
nsAutoArrayPtr<uint8_t> data(new (mozilla::fallible) uint8_t[aLength]);
|
||||
auto data = MakeUniqueFallible<uint8_t[]>(aLength);
|
||||
if (!data) {
|
||||
return mExecutor->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
@@ -1170,7 +1171,7 @@ nsHtml5StreamParser::OnDataAvailable(nsIRequest* aRequest,
|
||||
NS_ASSERTION(totalRead <= aLength, "Read more bytes than were available?");
|
||||
|
||||
nsCOMPtr<nsIRunnable> dataAvailable = new nsHtml5DataAvailable(this,
|
||||
data.forget(),
|
||||
Move(data),
|
||||
totalRead);
|
||||
if (NS_FAILED(mThread->Dispatch(dataAvailable, nsIThread::DISPATCH_NORMAL))) {
|
||||
NS_WARNING("Dispatching DataAvailable event failed.");
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "nsHtml5OwningUTF16Buffer.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsHtml5AtomTable.h"
|
||||
#include "nsHtml5Speculation.h"
|
||||
#include "nsITimer.h"
|
||||
@@ -398,7 +399,7 @@ class nsHtml5StreamParser : public nsICharsetDetectionObserver {
|
||||
/**
|
||||
* The buffer for sniffing the character encoding
|
||||
*/
|
||||
nsAutoArrayPtr<uint8_t> mSniffingBuffer;
|
||||
mozilla::UniquePtr<uint8_t[]> mSniffingBuffer;
|
||||
|
||||
/**
|
||||
* The number of meaningful bytes in mSniffingBuffer
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
nsHtml5TreeBuilder::nsHtml5TreeBuilder(nsHtml5OplessBuilder* aBuilder)
|
||||
: scriptingEnabled(false)
|
||||
@@ -128,7 +129,7 @@ nsHtml5TreeBuilder::createElement(int32_t aNamespace, nsIAtom* aName,
|
||||
nsString* crossOrigin =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_CROSSORIGIN);
|
||||
nsString* referrerPolicy =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRER);
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_REFERRERPOLICY);
|
||||
nsString* sizes =
|
||||
aAttributes->getValue(nsHtml5AttributeName::ATTR_SIZES);
|
||||
mSpeculativeLoadQueue.AppendElement()->
|
||||
@@ -997,8 +998,8 @@ nsHtml5TreeBuilder::AllocateContentHandle()
|
||||
return nullptr;
|
||||
}
|
||||
if (mHandlesUsed == NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH) {
|
||||
mOldHandles.AppendElement(mHandles.forget());
|
||||
mHandles = new nsIContent*[NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH];
|
||||
mOldHandles.AppendElement(Move(mHandles));
|
||||
mHandles = MakeUnique<nsIContent*[]>(NS_HTML5_TREE_BUILDER_HANDLE_ARRAY_LENGTH);
|
||||
mHandlesUsed = 0;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
nsTArray<nsHtml5TreeOperation> mOpQueue;
|
||||
nsTArray<nsHtml5SpeculativeLoad> mSpeculativeLoadQueue;
|
||||
nsAHtml5TreeOpSink* mOpSink;
|
||||
nsAutoArrayPtr<nsIContent*> mHandles;
|
||||
mozilla::UniquePtr<nsIContent*[]> mHandles;
|
||||
int32_t mHandlesUsed;
|
||||
nsTArray<nsAutoArrayPtr<nsIContent*> > mOldHandles;
|
||||
nsTArray<mozilla::UniquePtr<nsIContent*[]>> mOldHandles;
|
||||
nsHtml5TreeOpStage* mSpeculativeLoadStage;
|
||||
nsresult mBroken;
|
||||
bool mCurrentHtmlScriptIsAsyncOrDefer;
|
||||
|
||||
@@ -1051,6 +1051,15 @@ nsHtml5TreeOpExecutor::AddSpeculationCSP(const nsAString& aCSP)
|
||||
true); // delivered through the meta tag
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
// Record "speculated" referrer policy for preloads
|
||||
bool hasReferrerPolicy = false;
|
||||
uint32_t referrerPolicy = mozilla::net::RP_Default;
|
||||
rv = preloadCsp->GetReferrerPolicy(&referrerPolicy, &hasReferrerPolicy);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
if (hasReferrerPolicy) {
|
||||
SetSpeculationReferrerPolicy(static_cast<ReferrerPolicy>(referrerPolicy));
|
||||
}
|
||||
|
||||
mDocument->ApplySettingsFromCSP(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "nsUnicharInputStream.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
@@ -804,14 +805,21 @@ nsExpatDriver::OpenInputStreamFromExternalDTD(const char16_t* aFPIStr,
|
||||
NS_ASSERTION(mSink == nsCOMPtr<nsIExpatSink>(do_QueryInterface(mOriginalSink)),
|
||||
"In nsExpatDriver::OpenInputStreamFromExternalDTD: "
|
||||
"mOriginalSink not the same object as mSink?");
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
nsCOMPtr<nsIPrincipal> loadingPrincipal;
|
||||
if (mOriginalSink) {
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
doc = do_QueryInterface(mOriginalSink->GetTarget());
|
||||
if (doc) {
|
||||
loadingPrincipal = doc->NodePrincipal();
|
||||
}
|
||||
}
|
||||
if (!loadingPrincipal) {
|
||||
loadingPrincipal = nsNullPrincipal::Create();
|
||||
NS_ENSURE_TRUE(loadingPrincipal, NS_ERROR_FAILURE);
|
||||
}
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
doc,
|
||||
loadingPrincipal,
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
|
||||
nsILoadInfo::SEC_ALLOW_CHROME,
|
||||
nsIContentPolicy::TYPE_DTD);
|
||||
|
||||
@@ -14,287 +14,9 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
// C++ sucks! There's no way to do this with a macro, at least not
|
||||
// that I know, if you know how to do this with a macro then please do
|
||||
// so...
|
||||
static const char16_t sHTMLTagUnicodeName_a[] =
|
||||
{'a', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_abbr[] =
|
||||
{'a', 'b', 'b', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_acronym[] =
|
||||
{'a', 'c', 'r', 'o', 'n', 'y', 'm', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_address[] =
|
||||
{'a', 'd', 'd', 'r', 'e', 's', 's', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_applet[] =
|
||||
{'a', 'p', 'p', 'l', 'e', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_area[] =
|
||||
{'a', 'r', 'e', 'a', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_article[] =
|
||||
{'a', 'r', 't', 'i', 'c', 'l', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_aside[] =
|
||||
{'a', 's', 'i', 'd', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_audio[] =
|
||||
{'a', 'u', 'd', 'i', 'o', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_b[] =
|
||||
{'b', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_base[] =
|
||||
{'b', 'a', 's', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_basefont[] =
|
||||
{'b', 'a', 's', 'e', 'f', 'o', 'n', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_bdo[] =
|
||||
{'b', 'd', 'o', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_bgsound[] =
|
||||
{'b', 'g', 's', 'o', 'u', 'n', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_big[] =
|
||||
{'b', 'i', 'g', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_blockquote[] =
|
||||
{'b', 'l', 'o', 'c', 'k', 'q', 'u', 'o', 't', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_body[] =
|
||||
{'b', 'o', 'd', 'y', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_br[] =
|
||||
{'b', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_button[] =
|
||||
{'b', 'u', 't', 't', 'o', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_canvas[] =
|
||||
{'c', 'a', 'n', 'v', 'a', 's', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_caption[] =
|
||||
{'c', 'a', 'p', 't', 'i', 'o', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_center[] =
|
||||
{'c', 'e', 'n', 't', 'e', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_cite[] =
|
||||
{'c', 'i', 't', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_code[] =
|
||||
{'c', 'o', 'd', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_col[] =
|
||||
{'c', 'o', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_colgroup[] =
|
||||
{'c', 'o', 'l', 'g', 'r', 'o', 'u', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_content[] =
|
||||
{'c', 'o', 'n', 't', 'e', 'n', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_data[] =
|
||||
{'d', 'a', 't', 'a', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_datalist[] =
|
||||
{'d', 'a', 't', 'a', 'l', 'i', 's', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_dd[] =
|
||||
{'d', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_del[] =
|
||||
{'d', 'e', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_details[] =
|
||||
{'d', 'e', 't', 'a', 'i', 'l', 's', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_dfn[] =
|
||||
{'d', 'f', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_dir[] =
|
||||
{'d', 'i', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_div[] =
|
||||
{'d', 'i', 'v', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_dl[] =
|
||||
{'d', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_dt[] =
|
||||
{'d', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_em[] =
|
||||
{'e', 'm', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_embed[] =
|
||||
{'e', 'm', 'b', 'e', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_extapp[] =
|
||||
{'e', 'x', 't', 'a', 'p', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_fieldset[] =
|
||||
{'f', 'i', 'e', 'l', 'd', 's', 'e', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_figcaption[] =
|
||||
{'f', 'i', 'g', 'c', 'a', 'p', 't', 'i', 'o', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_figure[] =
|
||||
{'f', 'i', 'g', 'u', 'r', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_font[] =
|
||||
{'f', 'o', 'n', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_footer[] =
|
||||
{'f', 'o', 'o', 't', 'e', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_form[] =
|
||||
{'f', 'o', 'r', 'm', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_frame[] =
|
||||
{'f', 'r', 'a', 'm', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_frameset[] =
|
||||
{'f', 'r', 'a', 'm', 'e', 's', 'e', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_h1[] =
|
||||
{'h', '1', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_h2[] =
|
||||
{'h', '2', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_h3[] =
|
||||
{'h', '3', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_h4[] =
|
||||
{'h', '4', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_h5[] =
|
||||
{'h', '5', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_h6[] =
|
||||
{'h', '6', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_head[] =
|
||||
{'h', 'e', 'a', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_header[] =
|
||||
{'h', 'e', 'a', 'd', 'e', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_hgroup[] =
|
||||
{'h', 'g', 'r', 'o', 'u', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_hr[] =
|
||||
{'h', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_html[] =
|
||||
{'h', 't', 'm', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_i[] =
|
||||
{'i', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_iframe[] =
|
||||
{'i', 'f', 'r', 'a', 'm', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_image[] =
|
||||
{'i', 'm', 'a', 'g', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_img[] =
|
||||
{'i', 'm', 'g', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_input[] =
|
||||
{'i', 'n', 'p', 'u', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_ins[] =
|
||||
{'i', 'n', 's', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_kbd[] =
|
||||
{'k', 'b', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_keygen[] =
|
||||
{'k', 'e', 'y', 'g', 'e', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_label[] =
|
||||
{'l', 'a', 'b', 'e', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_legend[] =
|
||||
{'l', 'e', 'g', 'e', 'n', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_li[] =
|
||||
{'l', 'i', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_link[] =
|
||||
{'l', 'i', 'n', 'k', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_listing[] =
|
||||
{'l', 'i', 's', 't', 'i', 'n', 'g', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_main[] =
|
||||
{'m', 'a', 'i', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_map[] =
|
||||
{'m', 'a', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_mark[] =
|
||||
{'m', 'a', 'r', 'k', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_marquee[] =
|
||||
{'m', 'a', 'r', 'q', 'u', 'e', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_menu[] =
|
||||
{'m', 'e', 'n', 'u', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_menuitem[] =
|
||||
{'m', 'e', 'n', 'u', 'i', 't', 'e', 'm', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_meta[] =
|
||||
{'m', 'e', 't', 'a', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_meter[] =
|
||||
{'m', 'e', 't', 'e', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_multicol[] =
|
||||
{'m', 'u', 'l', 't', 'i', 'c', 'o', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_nav[] =
|
||||
{'n', 'a', 'v', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_nobr[] =
|
||||
{'n', 'o', 'b', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_noembed[] =
|
||||
{'n', 'o', 'e', 'm', 'b', 'e', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_noframes[] =
|
||||
{'n', 'o', 'f', 'r', 'a', 'm', 'e', 's', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_noscript[] =
|
||||
{'n', 'o', 's', 'c', 'r', 'i', 'p', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_object[] =
|
||||
{'o', 'b', 'j', 'e', 'c', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_ol[] =
|
||||
{'o', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_optgroup[] =
|
||||
{'o', 'p', 't', 'g', 'r', 'o', 'u', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_option[] =
|
||||
{'o', 'p', 't', 'i', 'o', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_output[] =
|
||||
{'o', 'u', 't', 'p', 'u', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_p[] =
|
||||
{'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_param[] =
|
||||
{'p', 'a', 'r', 'a', 'm', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_picture[] =
|
||||
{'p', 'i', 'c', 't', 'u', 'r', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_plaintext[] =
|
||||
{'p', 'l', 'a', 'i', 'n', 't', 'e', 'x', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_pre[] =
|
||||
{'p', 'r', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_progress[] =
|
||||
{'p', 'r', 'o', 'g', 'r', 'e', 's', 's', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_q[] =
|
||||
{'q', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_rb[] =
|
||||
{'r', 'b', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_rp[] =
|
||||
{'r', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_rt[] =
|
||||
{'r', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_rtc[] =
|
||||
{'r', 't', 'c', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_ruby[] =
|
||||
{'r', 'u', 'b', 'y', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_s[] =
|
||||
{'s', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_samp[] =
|
||||
{'s', 'a', 'm', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_script[] =
|
||||
{'s', 'c', 'r', 'i', 'p', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_section[] =
|
||||
{'s', 'e', 'c', 't', 'i', 'o', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_select[] =
|
||||
{'s', 'e', 'l', 'e', 'c', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_shadow[] =
|
||||
{'s', 'h', 'a', 'd', 'o', 'w', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_small[] =
|
||||
{'s', 'm', 'a', 'l', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_source[] =
|
||||
{'s', 'o', 'u', 'r', 'c', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_span[] =
|
||||
{'s', 'p', 'a', 'n', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_strike[] =
|
||||
{'s', 't', 'r', 'i', 'k', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_strong[] =
|
||||
{'s', 't', 'r', 'o', 'n', 'g', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_style[] =
|
||||
{'s', 't', 'y', 'l', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_sub[] =
|
||||
{'s', 'u', 'b', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_summary[] =
|
||||
{'s', 'u', 'm', 'm', 'a', 'r', 'y', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_sup[] =
|
||||
{'s', 'u', 'p', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_table[] =
|
||||
{'t', 'a', 'b', 'l', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_tbody[] =
|
||||
{'t', 'b', 'o', 'd', 'y', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_td[] =
|
||||
{'t', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_textarea[] =
|
||||
{'t', 'e', 'x', 't', 'a', 'r', 'e', 'a', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_tfoot[] =
|
||||
{'t', 'f', 'o', 'o', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_th[] =
|
||||
{'t', 'h', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_thead[] =
|
||||
{'t', 'h', 'e', 'a', 'd', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_template[] =
|
||||
{'t', 'e', 'm', 'p', 'l', 'a', 't', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_time[] =
|
||||
{'t', 'i', 'm', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_title[] =
|
||||
{'t', 'i', 't', 'l', 'e', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_tr[] =
|
||||
{'t', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_track[] =
|
||||
{'t', 'r', 'a', 'c', 'k', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_tt[] =
|
||||
{'t', 't', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_u[] =
|
||||
{'u', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_ul[] =
|
||||
{'u', 'l', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_var[] =
|
||||
{'v', 'a', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_video[] =
|
||||
{'v', 'i', 'd', 'e', 'o', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_wbr[] =
|
||||
{'w', 'b', 'r', '\0'};
|
||||
static const char16_t sHTMLTagUnicodeName_xmp[] =
|
||||
{'x', 'm', 'p', '\0'};
|
||||
|
||||
// static array of unicode tag names
|
||||
#define HTML_TAG(_tag, _classname) sHTMLTagUnicodeName_##_tag,
|
||||
#define HTML_HTMLELEMENT_TAG(_tag) sHTMLTagUnicodeName_##_tag,
|
||||
#define HTML_TAG(_tag, _classname) MOZ_UTF16(#_tag),
|
||||
#define HTML_HTMLELEMENT_TAG(_tag) MOZ_UTF16(#_tag),
|
||||
#define HTML_OTHER(_tag)
|
||||
const char16_t* const nsHTMLTags::sTagUnicodeTable[] = {
|
||||
#include "nsHTMLTagList.h"
|
||||
|
||||
@@ -385,4 +385,47 @@ test(function() {
|
||||
el.removeAttributeNS(null, "pre:fix")
|
||||
assert_equals(el.attributes[0], unprefixed)
|
||||
}, "Attribute with prefix in local name")
|
||||
|
||||
test(function() {
|
||||
var el = document.createElement("div")
|
||||
el.setAttribute("foo", "bar")
|
||||
var attr = el.attributes[0]
|
||||
assert_equals(attr.ownerElement, el)
|
||||
el.removeAttribute("foo")
|
||||
assert_equals(attr.ownerElement, null)
|
||||
}, "Attribute loses its owner when removed")
|
||||
|
||||
test(function() {
|
||||
var el = document.createElement("div");
|
||||
el.setAttribute("foo", "bar");
|
||||
assert_equals(el.getAttributeNames().length, 1);
|
||||
assert_equals(el.getAttributeNames()[0], el.attributes[0].name);
|
||||
assert_equals(el.getAttributeNames()[0], "foo");
|
||||
|
||||
el.removeAttribute("foo");
|
||||
assert_equals(el.getAttributeNames().length, 0);
|
||||
|
||||
el.setAttribute("foo", "bar");
|
||||
el.setAttributeNS("", "FOO", "bar");
|
||||
el.setAttributeNS("dummy1", "foo", "bar");
|
||||
el.setAttributeNS("dummy2", "dummy:foo", "bar");
|
||||
assert_equals(el.getAttributeNames().length, 4);
|
||||
assert_equals(el.getAttributeNames()[0], "foo");
|
||||
assert_equals(el.getAttributeNames()[1], "FOO");
|
||||
assert_equals(el.getAttributeNames()[2], "foo");
|
||||
assert_equals(el.getAttributeNames()[3], "dummy:foo");
|
||||
assert_equals(el.getAttributeNames()[0], el.attributes[0].name);
|
||||
assert_equals(el.getAttributeNames()[1], el.attributes[1].name);
|
||||
assert_equals(el.getAttributeNames()[2], el.attributes[2].name);
|
||||
assert_equals(el.getAttributeNames()[3], el.attributes[3].name);
|
||||
|
||||
el.removeAttributeNS("", "FOO");
|
||||
assert_equals(el.getAttributeNames().length, 3);
|
||||
assert_equals(el.getAttributeNames()[0], "foo");
|
||||
assert_equals(el.getAttributeNames()[1], "foo");
|
||||
assert_equals(el.getAttributeNames()[2], "dummy:foo");
|
||||
assert_equals(el.getAttributeNames()[0], el.attributes[0].name);
|
||||
assert_equals(el.getAttributeNames()[1], el.attributes[1].name);
|
||||
assert_equals(el.getAttributeNames()[2], el.attributes[2].name);
|
||||
}, "getAttributeNames tests");
|
||||
</script>
|
||||
|
||||
+67
-48
@@ -448,11 +448,10 @@ ContentCacheInChild::SetSelection(nsIWidget* aWidget,
|
||||
|
||||
ContentCacheInParent::ContentCacheInParent()
|
||||
: ContentCache()
|
||||
, mCommitStringByRequest(nullptr)
|
||||
, mCompositionStart(UINT32_MAX)
|
||||
, mCompositionEventsDuringRequest(0)
|
||||
, mPendingEventsNeedingAck(0)
|
||||
, mIsComposing(false)
|
||||
, mRequestedToCommitOrCancelComposition(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -827,48 +826,34 @@ ContentCacheInParent::OnCompositionEvent(const WidgetCompositionEvent& aEvent)
|
||||
("ContentCacheInParent: 0x%p OnCompositionEvent(aEvent={ "
|
||||
"mMessage=%s, mData=\"%s\" (Length()=%u), mRanges->Length()=%u }), "
|
||||
"mPendingEventsNeedingAck=%u, mIsComposing=%s, "
|
||||
"mRequestedToCommitOrCancelComposition=%s",
|
||||
"mCommitStringByRequest=0x%p",
|
||||
this, ToChar(aEvent.mMessage),
|
||||
NS_ConvertUTF16toUTF8(aEvent.mData).get(), aEvent.mData.Length(),
|
||||
aEvent.mRanges ? aEvent.mRanges->Length() : 0, mPendingEventsNeedingAck,
|
||||
GetBoolName(mIsComposing),
|
||||
GetBoolName(mRequestedToCommitOrCancelComposition)));
|
||||
|
||||
if (!aEvent.CausesDOMTextEvent()) {
|
||||
MOZ_ASSERT(aEvent.mMessage == eCompositionStart);
|
||||
mIsComposing = !aEvent.CausesDOMCompositionEndEvent();
|
||||
mCompositionStart = mSelection.StartOffset();
|
||||
// XXX What's this case??
|
||||
if (mRequestedToCommitOrCancelComposition) {
|
||||
mCommitStringByRequest = aEvent.mData;
|
||||
mCompositionEventsDuringRequest++;
|
||||
return false;
|
||||
}
|
||||
mPendingEventsNeedingAck++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX Why do we ignore following composition events here?
|
||||
// TextComposition must handle following events correctly!
|
||||
|
||||
// During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION,
|
||||
// widget usually sends a eCompositionChange event to finalize or
|
||||
// clear the composition, respectively.
|
||||
// Because the event will not reach content in time, we intercept it
|
||||
// here and pass the text as the DidRequestToCommitOrCancelComposition()
|
||||
// return value.
|
||||
if (mRequestedToCommitOrCancelComposition) {
|
||||
mCommitStringByRequest = aEvent.mData;
|
||||
mCompositionEventsDuringRequest++;
|
||||
return false;
|
||||
}
|
||||
GetBoolName(mIsComposing), mCommitStringByRequest));
|
||||
|
||||
// We must be able to simulate the selection because
|
||||
// we might not receive selection updates in time
|
||||
if (!mIsComposing) {
|
||||
mCompositionStart = mSelection.StartOffset();
|
||||
}
|
||||
|
||||
mIsComposing = !aEvent.CausesDOMCompositionEndEvent();
|
||||
|
||||
// During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION,
|
||||
// widget usually sends a eCompositionChange and/or eCompositionCommit event
|
||||
// to finalize or clear the composition, respectively. In this time,
|
||||
// we need to intercept all composition events here and pass the commit
|
||||
// string for returning to the remote process as a result of
|
||||
// RequestIMEToCommitComposition(). Then, eCommitComposition event will
|
||||
// be dispatched with the committed string in the remote process internally.
|
||||
if (mCommitStringByRequest) {
|
||||
MOZ_ASSERT(aEvent.mMessage == eCompositionChange ||
|
||||
aEvent.mMessage == eCompositionCommit);
|
||||
*mCommitStringByRequest = aEvent.mData;
|
||||
return false;
|
||||
}
|
||||
|
||||
mPendingEventsNeedingAck++;
|
||||
return true;
|
||||
}
|
||||
@@ -912,29 +897,63 @@ ContentCacheInParent::OnEventNeedingAckHandled(nsIWidget* aWidget,
|
||||
FlushPendingNotifications(aWidget);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ContentCacheInParent::RequestToCommitComposition(nsIWidget* aWidget,
|
||||
bool aCancel,
|
||||
nsAString& aLastString)
|
||||
bool
|
||||
ContentCacheInParent::RequestIMEToCommitComposition(nsIWidget* aWidget,
|
||||
bool aCancel,
|
||||
nsAString& aCommittedString)
|
||||
{
|
||||
MOZ_LOG(sContentCacheLog, LogLevel::Info,
|
||||
("ContentCacheInParent: 0x%p RequestToCommitComposition(aWidget=%p, "
|
||||
"aCancel=%s), mIsComposing=%s, mRequestedToCommitOrCancelComposition=%s, "
|
||||
"mCompositionEventsDuringRequest=%u",
|
||||
"aCancel=%s), mIsComposing=%s, mCommitStringByRequest=%p",
|
||||
this, aWidget, GetBoolName(aCancel), GetBoolName(mIsComposing),
|
||||
GetBoolName(mRequestedToCommitOrCancelComposition),
|
||||
mCompositionEventsDuringRequest));
|
||||
mCommitStringByRequest));
|
||||
|
||||
mRequestedToCommitOrCancelComposition = true;
|
||||
mCompositionEventsDuringRequest = 0;
|
||||
MOZ_ASSERT(!mCommitStringByRequest);
|
||||
|
||||
RefPtr<TextComposition> composition =
|
||||
IMEStateManager::GetTextCompositionFor(aWidget);
|
||||
if (NS_WARN_IF(!composition)) {
|
||||
MOZ_LOG(sContentCacheLog, LogLevel::Warning,
|
||||
(" ContentCacheInParent: 0x%p RequestToCommitComposition(), "
|
||||
"does nothing due to no composition", this));
|
||||
return false;
|
||||
}
|
||||
|
||||
mCommitStringByRequest = &aCommittedString;
|
||||
|
||||
aWidget->NotifyIME(IMENotification(aCancel ? REQUEST_TO_CANCEL_COMPOSITION :
|
||||
REQUEST_TO_COMMIT_COMPOSITION));
|
||||
|
||||
mRequestedToCommitOrCancelComposition = false;
|
||||
aLastString = mCommitStringByRequest;
|
||||
mCommitStringByRequest.Truncate(0);
|
||||
return mCompositionEventsDuringRequest;
|
||||
mCommitStringByRequest = nullptr;
|
||||
|
||||
MOZ_LOG(sContentCacheLog, LogLevel::Info,
|
||||
(" ContentCacheInParent: 0x%p RequestToCommitComposition(), "
|
||||
"mIsComposing=%s, the composition %s committed synchronously",
|
||||
this, GetBoolName(mIsComposing),
|
||||
composition->Destroyed() ? "WAS" : "has NOT been"));
|
||||
|
||||
if (!composition->Destroyed()) {
|
||||
// When the composition isn't committed synchronously, the remote process's
|
||||
// TextComposition instance will synthesize commit events and wait to
|
||||
// receive delayed composition events. When TextComposition instances both
|
||||
// in this process and the remote process will be destroyed when delayed
|
||||
// composition events received. TextComposition instance in the parent
|
||||
// process will dispatch following composition events and be destroyed
|
||||
// normally. On the other hand, TextComposition instance in the remote
|
||||
// process won't dispatch following composition events and will be
|
||||
// destroyed by IMEStateManager::DispatchCompositionEvent().
|
||||
return false;
|
||||
}
|
||||
|
||||
// When the composition is committed synchronously, the commit string will be
|
||||
// returned to the remote process. Then, PuppetWidget will dispatch
|
||||
// eCompositionCommit event with the returned commit string (i.e., the value
|
||||
// is aCommittedString of this method). Finally, TextComposition instance in
|
||||
// the remote process will be destroyed by
|
||||
// IMEStateManager::DispatchCompositionEvent() at receiving the
|
||||
// eCompositionCommit event (Note that TextComposition instance in this
|
||||
// process was already destroyed).
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
+14
-16
@@ -325,22 +325,22 @@ public:
|
||||
void OnEventNeedingAckHandled(nsIWidget* aWidget, EventMessage aMessage);
|
||||
|
||||
/**
|
||||
* RequestToCommitComposition() requests to commit or cancel composition to
|
||||
* the widget. If it's handled synchronously, this returns the number of
|
||||
* composition events after that.
|
||||
* RequestIMEToCommitComposition() requests aWidget to commit or cancel
|
||||
* composition. If it's handled synchronously, this returns true.
|
||||
*
|
||||
* @param aWidget The widget to be requested to commit or cancel
|
||||
* the composition.
|
||||
* @param aCancel When the caller tries to cancel the composition, true.
|
||||
* Otherwise, i.e., tries to commit the composition, false.
|
||||
* @param aLastString The last composition string before requesting to
|
||||
* commit or cancel composition.
|
||||
* @return The count of composition events ignored after a call of
|
||||
* WillRequestToCommitOrCancelComposition().
|
||||
* @param aCommittedString The committed string (i.e., the last data of
|
||||
* dispatched composition events during requesting
|
||||
* IME to commit composition.
|
||||
* @return Whether the composition is actually committed
|
||||
* synchronously.
|
||||
*/
|
||||
uint32_t RequestToCommitComposition(nsIWidget* aWidget,
|
||||
bool aCancel,
|
||||
nsAString& aLastString);
|
||||
bool RequestIMEToCommitComposition(nsIWidget* aWidget,
|
||||
bool aCancel,
|
||||
nsAString& aCommittedString);
|
||||
|
||||
/**
|
||||
* MaybeNotifyIME() may notify IME of the notification. If child process
|
||||
@@ -356,20 +356,18 @@ private:
|
||||
IMENotification mPendingLayoutChange;
|
||||
IMENotification mPendingCompositionUpdate;
|
||||
|
||||
// This is commit string which is caused by our request.
|
||||
nsString mCommitStringByRequest;
|
||||
// This is not nullptr only while the instance is requesting IME to
|
||||
// composition. Then, data value of dispatched composition events should
|
||||
// be stored into the instance.
|
||||
nsAString* mCommitStringByRequest;
|
||||
// Start offset of the composition string.
|
||||
uint32_t mCompositionStart;
|
||||
// Count of composition events during requesting commit or cancel the
|
||||
// composition.
|
||||
uint32_t mCompositionEventsDuringRequest;
|
||||
// mPendingEventsNeedingAck is increased before sending a composition event or
|
||||
// a selection event and decreased after they are received in the child
|
||||
// process.
|
||||
uint32_t mPendingEventsNeedingAck;
|
||||
|
||||
bool mIsComposing;
|
||||
bool mRequestedToCommitOrCancelComposition;
|
||||
|
||||
bool GetCaretRect(uint32_t aOffset, LayoutDeviceIntRect& aCaretRect) const;
|
||||
bool GetTextRect(uint32_t aOffset,
|
||||
|
||||
+51
-7
@@ -10,6 +10,8 @@
|
||||
#include "nsRect.h"
|
||||
#include "nsStringGlue.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WritingMode;
|
||||
@@ -224,11 +226,58 @@ struct IMEState final
|
||||
}
|
||||
};
|
||||
|
||||
// NS_ONLY_ONE_NATIVE_IME_CONTEXT is a special value of native IME context.
|
||||
// If there can be only one IME composition in a process, this can be used.
|
||||
#define NS_ONLY_ONE_NATIVE_IME_CONTEXT \
|
||||
(reinterpret_cast<void*>(static_cast<intptr_t>(-1)))
|
||||
|
||||
struct NativeIMEContext final
|
||||
{
|
||||
// Pointer to native IME context. Typically this is the result of
|
||||
// nsIWidget::GetNativeData(NS_RAW_NATIVE_IME_CONTEXT) in the parent process.
|
||||
// See also NS_ONLY_ONE_NATIVE_IME_CONTEXT.
|
||||
uintptr_t mRawNativeIMEContext;
|
||||
// Process ID of the origin of mNativeIMEContext.
|
||||
uint64_t mOriginProcessID;
|
||||
|
||||
NativeIMEContext()
|
||||
{
|
||||
Init(nullptr);
|
||||
}
|
||||
|
||||
explicit NativeIMEContext(nsIWidget* aWidget)
|
||||
{
|
||||
Init(aWidget);
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return mRawNativeIMEContext &&
|
||||
mOriginProcessID != static_cast<uintptr_t>(-1);
|
||||
}
|
||||
|
||||
void Init(nsIWidget* aWidget);
|
||||
void InitWithRawNativeIMEContext(const void* aRawNativeIMEContext)
|
||||
{
|
||||
InitWithRawNativeIMEContext(const_cast<void*>(aRawNativeIMEContext));
|
||||
}
|
||||
void InitWithRawNativeIMEContext(void* aRawNativeIMEContext);
|
||||
|
||||
bool operator==(const NativeIMEContext& aOther) const
|
||||
{
|
||||
return mRawNativeIMEContext == aOther.mRawNativeIMEContext &&
|
||||
mOriginProcessID == aOther.mOriginProcessID;
|
||||
}
|
||||
bool operator!=(const NativeIMEContext& aOther) const
|
||||
{
|
||||
return !(*this == aOther);
|
||||
}
|
||||
};
|
||||
|
||||
struct InputContext final
|
||||
{
|
||||
InputContext()
|
||||
: mNativeIMEContext(nullptr)
|
||||
, mOrigin(XRE_IsParentProcess() ? ORIGIN_MAIN : ORIGIN_CONTENT)
|
||||
: mOrigin(XRE_IsParentProcess() ? ORIGIN_MAIN : ORIGIN_CONTENT)
|
||||
, mMayBeIMEUnaware(false)
|
||||
{
|
||||
}
|
||||
@@ -249,11 +298,6 @@ struct InputContext final
|
||||
/* A hint for the action that is performed when the input is submitted */
|
||||
nsString mActionHint;
|
||||
|
||||
/* Native IME context for the widget. This doesn't come from the argument of
|
||||
SetInputContext(). If there is only one context in the process, this may
|
||||
be nullptr. */
|
||||
void* mNativeIMEContext;
|
||||
|
||||
/**
|
||||
* mOrigin indicates whether this focus event refers to main or remote
|
||||
* content.
|
||||
|
||||
+77
-25
@@ -79,9 +79,9 @@ PuppetWidget::PuppetWidget(TabChild* aTabChild)
|
||||
, mMemoryPressureObserver(nullptr)
|
||||
, mDPI(-1)
|
||||
, mDefaultScale(-1)
|
||||
, mNativeKeyCommandsValid(false)
|
||||
, mCursorHotspotX(0)
|
||||
, mCursorHotspotY(0)
|
||||
, mNativeKeyCommandsValid(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(PuppetWidget);
|
||||
|
||||
@@ -159,6 +159,11 @@ PuppetWidget::CreateChild(const LayoutDeviceIntRect& aRect,
|
||||
NS_IMETHODIMP
|
||||
PuppetWidget::Destroy()
|
||||
{
|
||||
if (mOnDestroyCalled) {
|
||||
return NS_OK;
|
||||
}
|
||||
mOnDestroyCalled = true;
|
||||
|
||||
Base::OnDestroy();
|
||||
Base::Destroy();
|
||||
mPaintTask.Revoke();
|
||||
@@ -317,6 +322,24 @@ PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
|
||||
}
|
||||
}
|
||||
|
||||
if (event->mClass == eCompositionEventClass) {
|
||||
// Store the latest native IME context of parent process's widget or
|
||||
// TextEventDispatcher if it's in this process.
|
||||
WidgetCompositionEvent* compositionEvent = event->AsCompositionEvent();
|
||||
#ifdef DEBUG
|
||||
if (mNativeIMEContext.IsValid() &&
|
||||
mNativeIMEContext != compositionEvent->mNativeIMEContext) {
|
||||
RefPtr<TextComposition> composition =
|
||||
IMEStateManager::GetTextCompositionFor(this);
|
||||
MOZ_ASSERT(!composition,
|
||||
"When there is composition caused by old native IME context, "
|
||||
"composition events caused by different native IME context are not "
|
||||
"allowed");
|
||||
}
|
||||
#endif // #ifdef DEBUG
|
||||
mNativeIMEContext = compositionEvent->mNativeIMEContext;
|
||||
}
|
||||
|
||||
aStatus = nsEventStatus_eIgnore;
|
||||
|
||||
if (GetCurrentWidgetListener()) {
|
||||
@@ -566,29 +589,51 @@ PuppetWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
||||
}
|
||||
|
||||
nsresult
|
||||
PuppetWidget::IMEEndComposition(bool aCancel)
|
||||
PuppetWidget::RequestIMEToCommitComposition(bool aCancel)
|
||||
{
|
||||
#ifndef MOZ_CROSS_PROCESS_IME
|
||||
return NS_OK;
|
||||
#endif
|
||||
|
||||
nsEventStatus status;
|
||||
bool noCompositionEvent = true;
|
||||
WidgetCompositionEvent compositionCommitEvent(true, eCompositionCommit, this);
|
||||
InitEvent(compositionCommitEvent, nullptr);
|
||||
// SendEndIMEComposition is always called since ResetInputState
|
||||
// should always be called even if we aren't composing something.
|
||||
if (!mTabChild ||
|
||||
!mTabChild->SendEndIMEComposition(aCancel, &noCompositionEvent,
|
||||
&compositionCommitEvent.mData)) {
|
||||
#ifdef MOZ_CROSS_PROCESS_IME
|
||||
if (!mTabChild) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (noCompositionEvent) {
|
||||
MOZ_ASSERT(!Destroyed());
|
||||
|
||||
// There must not be composition which is caused by the PuppetWidget instance.
|
||||
if (NS_WARN_IF(!mNativeIMEContext.IsValid())) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<TextComposition> composition =
|
||||
IMEStateManager::GetTextCompositionFor(this);
|
||||
// This method shouldn't be called when there is no text composition instance.
|
||||
if (NS_WARN_IF(!composition)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool isCommitted = false;
|
||||
nsAutoString committedString;
|
||||
if (NS_WARN_IF(!mTabChild->SendRequestIMEToCommitComposition(
|
||||
aCancel, &isCommitted, &committedString))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// If the composition wasn't committed synchronously, we need to wait async
|
||||
// composition events for destroying the TextComposition instance.
|
||||
if (!isCommitted) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Dispatch eCompositionCommit event.
|
||||
WidgetCompositionEvent compositionCommitEvent(true, eCompositionCommit, this);
|
||||
InitEvent(compositionCommitEvent, nullptr);
|
||||
compositionCommitEvent.mData = committedString;
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
DispatchEvent(&compositionCommitEvent, status);
|
||||
|
||||
// NOTE: PuppetWidget might be destroyed already.
|
||||
|
||||
#endif // #ifdef MOZ_CROSS_PROCESS_IME
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -597,9 +642,9 @@ PuppetWidget::NotifyIMEInternal(const IMENotification& aIMENotification)
|
||||
{
|
||||
switch (aIMENotification.mMessage) {
|
||||
case REQUEST_TO_COMMIT_COMPOSITION:
|
||||
return IMEEndComposition(false);
|
||||
return RequestIMEToCommitComposition(false);
|
||||
case REQUEST_TO_CANCEL_COMPOSITION:
|
||||
return IMEEndComposition(true);
|
||||
return RequestIMEToCommitComposition(true);
|
||||
case NOTIFY_IME_OF_FOCUS:
|
||||
case NOTIFY_IME_OF_BLUR:
|
||||
return NotifyIMEOfFocusChange(aIMENotification);
|
||||
@@ -673,15 +718,20 @@ PuppetWidget::GetInputContext()
|
||||
InputContext context;
|
||||
if (mTabChild) {
|
||||
int32_t enabled, open;
|
||||
intptr_t nativeIMEContext;
|
||||
mTabChild->SendGetInputContext(&enabled, &open, &nativeIMEContext);
|
||||
// TODO: This is too expensive. PuppetWidget should cache IMEState.
|
||||
mTabChild->SendGetInputContext(&enabled, &open);
|
||||
context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(enabled);
|
||||
context.mIMEState.mOpen = static_cast<IMEState::Open>(open);
|
||||
context.mNativeIMEContext = reinterpret_cast<void*>(nativeIMEContext);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(NativeIMEContext)
|
||||
PuppetWidget::GetNativeIMEContext()
|
||||
{
|
||||
return mNativeIMEContext;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PuppetWidget::NotifyIMEOfFocusChange(const IMENotification& aIMENotification)
|
||||
{
|
||||
@@ -1115,14 +1165,16 @@ PuppetWidget::GetNativeData(uint32_t aDataType)
|
||||
}
|
||||
return (void*)nativeData;
|
||||
}
|
||||
case NS_NATIVE_WINDOW:
|
||||
case NS_NATIVE_WIDGET:
|
||||
case NS_NATIVE_DISPLAY:
|
||||
// These types are ignored (see bug 1183828).
|
||||
break;
|
||||
case NS_RAW_NATIVE_IME_CONTEXT:
|
||||
MOZ_CRASH("You need to call GetNativeIMEContext() instead");
|
||||
case NS_NATIVE_WINDOW:
|
||||
case NS_NATIVE_PLUGIN_PORT:
|
||||
case NS_NATIVE_GRAPHIC:
|
||||
case NS_NATIVE_SHELLWIDGET:
|
||||
case NS_NATIVE_WIDGET:
|
||||
NS_WARNING("nsWindow::GetNativeData not implemented for this type");
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("nsWindow::GetNativeData called with bad value");
|
||||
break;
|
||||
|
||||
+16
-6
@@ -179,6 +179,7 @@ public:
|
||||
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
|
||||
const InputContextAction& aAction) override;
|
||||
NS_IMETHOD_(InputContext) GetInputContext() override;
|
||||
NS_IMETHOD_(NativeIMEContext) GetNativeIMEContext() override;
|
||||
virtual nsIMEUpdatePreference GetIMEUpdatePreference() override;
|
||||
|
||||
NS_IMETHOD SetCursor(nsCursor aCursor) override;
|
||||
@@ -254,9 +255,6 @@ public:
|
||||
|
||||
virtual void StartAsyncScrollbarDrag(const AsyncDragMetrics& aDragMetrics) override;
|
||||
protected:
|
||||
bool mEnabled;
|
||||
bool mVisible;
|
||||
|
||||
virtual nsresult NotifyIMEInternal(
|
||||
const IMENotification& aIMENotification) override;
|
||||
|
||||
@@ -265,7 +263,7 @@ private:
|
||||
|
||||
void SetChild(PuppetWidget* aChild);
|
||||
|
||||
nsresult IMEEndComposition(bool aCancel);
|
||||
nsresult RequestIMEToCommitComposition(bool aCancel);
|
||||
nsresult NotifyIMEOfFocusChange(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfSelectionChange(const IMENotification& aIMENotification);
|
||||
nsresult NotifyIMEOfCompositionUpdate(const IMENotification& aIMENotification);
|
||||
@@ -322,21 +320,33 @@ private:
|
||||
// IME
|
||||
nsIMEUpdatePreference mIMEPreferenceOfParent;
|
||||
InputContext mInputContext;
|
||||
// mNativeIMEContext is initialized when this dispatches every composition
|
||||
// event both from parent process's widget and TextEventDispatcher in same
|
||||
// process. If it hasn't been started composition yet, this isn't necessary
|
||||
// for XP code since there is no TextComposition instance which is caused by
|
||||
// the PuppetWidget instance.
|
||||
NativeIMEContext mNativeIMEContext;
|
||||
ContentCacheInChild mContentCache;
|
||||
bool mNeedIMEStateInit;
|
||||
|
||||
// The DPI of the screen corresponding to this widget
|
||||
float mDPI;
|
||||
double mDefaultScale;
|
||||
|
||||
// Precomputed answers for ExecuteNativeKeyBinding
|
||||
bool mNativeKeyCommandsValid;
|
||||
InfallibleTArray<mozilla::CommandInt> mSingleLineCommands;
|
||||
InfallibleTArray<mozilla::CommandInt> mMultiLineCommands;
|
||||
InfallibleTArray<mozilla::CommandInt> mRichTextCommands;
|
||||
|
||||
nsCOMPtr<imgIContainer> mCustomCursor;
|
||||
uint32_t mCursorHotspotX, mCursorHotspotY;
|
||||
|
||||
protected:
|
||||
bool mEnabled;
|
||||
bool mVisible;
|
||||
|
||||
private:
|
||||
bool mNeedIMEStateInit;
|
||||
bool mNativeKeyCommandsValid;
|
||||
};
|
||||
|
||||
struct AutoCacheNativeKeyCommands
|
||||
|
||||
@@ -134,6 +134,17 @@ TextEventDispatcher::InitEvent(WidgetGUIEvent& aEvent) const
|
||||
aEvent.time = PR_IntervalNow();
|
||||
aEvent.refPoint = LayoutDeviceIntPoint(0, 0);
|
||||
aEvent.mFlags.mIsSynthesizedForTests = mForTests;
|
||||
if (aEvent.mClass != eCompositionEventClass) {
|
||||
return;
|
||||
}
|
||||
// Currently, we should set special native IME context when composition
|
||||
// events are dispatched from PuppetWidget since PuppetWidget may have not
|
||||
// known actual native IME context yet and it caches native IME context
|
||||
// when it dispatches every WidgetCompositionEvent.
|
||||
if (XRE_IsContentProcess()) {
|
||||
aEvent.AsCompositionEvent()->
|
||||
mNativeIMEContext.InitWithRawNativeIMEContext(mWidget);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
||||
@@ -366,6 +366,7 @@ public:
|
||||
WidgetCompositionEvent(bool aIsTrusted, EventMessage aMessage,
|
||||
nsIWidget* aWidget)
|
||||
: WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eCompositionEventClass)
|
||||
, mNativeIMEContext(aWidget)
|
||||
, mOriginalMessage(eVoidEvent)
|
||||
{
|
||||
// XXX compositionstart is cancelable in draft of DOM3 Events.
|
||||
@@ -393,6 +394,10 @@ public:
|
||||
|
||||
RefPtr<TextRangeArray> mRanges;
|
||||
|
||||
// mNativeIMEContext stores the native IME context which causes the
|
||||
// composition event.
|
||||
widget::NativeIMEContext mNativeIMEContext;
|
||||
|
||||
// If the instance is a clone of another event, mOriginalMessage stores
|
||||
// the another event's mMessage.
|
||||
EventMessage mOriginalMessage;
|
||||
|
||||
@@ -684,6 +684,17 @@ void* nsChildView::GetNativeData(uint32_t aDataType)
|
||||
case NS_NATIVE_OFFSETY:
|
||||
retVal = 0;
|
||||
break;
|
||||
|
||||
case NS_RAW_NATIVE_IME_CONTEXT:
|
||||
retVal = [mView inputContext];
|
||||
// If input context isn't available on this widget, we should set |this|
|
||||
// instead of nullptr since if this returns nullptr, IMEStateManager
|
||||
// cannot manage composition with TextComposition instance. Although,
|
||||
// this case shouldn't occur.
|
||||
if (NS_WARN_IF(!retVal)) {
|
||||
retVal = this;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@@ -1769,13 +1780,6 @@ nsChildView::GetInputContext()
|
||||
mInputContext.mIMEState.mOpen = IMEState::CLOSED;
|
||||
break;
|
||||
}
|
||||
mInputContext.mNativeIMEContext = [mView inputContext];
|
||||
// If input context isn't available on this widget, we should set |this|
|
||||
// instead of nullptr since nullptr means that the platform has only one
|
||||
// context per process.
|
||||
if (!mInputContext.mNativeIMEContext) {
|
||||
mInputContext.mNativeIMEContext = this;
|
||||
}
|
||||
return mInputContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -349,16 +349,6 @@ public:
|
||||
const InputContextAction& aAction) override;
|
||||
NS_IMETHOD_(InputContext) GetInputContext() override
|
||||
{
|
||||
NSView* view = mWindow ? [mWindow contentView] : nil;
|
||||
if (view) {
|
||||
mInputContext.mNativeIMEContext = [view inputContext];
|
||||
}
|
||||
// If inputContext isn't available on this window, returns this window's
|
||||
// pointer since nullptr means the platform has only one context per
|
||||
// process.
|
||||
if (!mInputContext.mNativeIMEContext) {
|
||||
mInputContext.mNativeIMEContext = this;
|
||||
}
|
||||
return mInputContext;
|
||||
}
|
||||
NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
|
||||
|
||||
@@ -581,6 +581,20 @@ void* nsCocoaWindow::GetNativeData(uint32_t aDataType)
|
||||
// and it doesn't matter so just return nullptr.
|
||||
NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a top-level window!");
|
||||
break;
|
||||
case NS_RAW_NATIVE_IME_CONTEXT: {
|
||||
NSView* view = mWindow ? [mWindow contentView] : nil;
|
||||
if (view) {
|
||||
retVal = [view inputContext];
|
||||
}
|
||||
// If inputContext isn't available on this window, return this window's
|
||||
// pointer instead of nullptr since if this returns nullptr,
|
||||
// IMEStateManager cannot manage composition with TextComposition
|
||||
// instance. Although, this case shouldn't occur.
|
||||
if (NS_WARN_IF(!retVal)) {
|
||||
retVal = this;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
|
||||
@@ -446,9 +446,18 @@ nsScreenGonk::GetEGLDisplay()
|
||||
hwc_surface_t
|
||||
nsScreenGonk::GetEGLSurface()
|
||||
{
|
||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||
return mEGLSurface;
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::gl::GLContext>
|
||||
nsScreenGonk::GetGLContext()
|
||||
{
|
||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||
RefPtr<mozilla::gl::GLContext>glContext = mGLContext;
|
||||
return glContext.forget();
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateMirroringWidgetSync(RefPtr<nsScreenGonk>&& aScreen, nsWindow* aWindow)
|
||||
{
|
||||
|
||||
@@ -117,6 +117,7 @@ public:
|
||||
mozilla::gl::GLContext* aGLContext);
|
||||
hwc_display_t GetEGLDisplay();
|
||||
hwc_surface_t GetEGLSurface();
|
||||
already_AddRefed<mozilla::gl::GLContext> GetGLContext();
|
||||
void UpdateMirroringWidget(already_AddRefed<nsWindow>& aWindow); // Primary screen only
|
||||
nsWindow* GetMirroringWidget(); // Primary screen only
|
||||
|
||||
|
||||
@@ -537,7 +537,13 @@ nsWindow::GetNativeData(uint32_t aDataType)
|
||||
case NS_NATIVE_WINDOW:
|
||||
// Called before primary display's EGLSurface creation.
|
||||
return mScreen->GetNativeWindow();
|
||||
case NS_NATIVE_OPENGL_CONTEXT:
|
||||
return mScreen->GetGLContext().take();
|
||||
case NS_RAW_NATIVE_IME_CONTEXT:
|
||||
// There is only one IME context on Gonk.
|
||||
return NS_ONLY_ONE_NATIVE_IME_CONTEXT;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -579,8 +585,6 @@ nsWindow::SetInputContext(const InputContext& aContext,
|
||||
NS_IMETHODIMP_(InputContext)
|
||||
nsWindow::GetInputContext()
|
||||
{
|
||||
// There is only one IME context on Gonk.
|
||||
mInputContext.mNativeIMEContext = nullptr;
|
||||
return mInputContext;
|
||||
}
|
||||
|
||||
@@ -747,7 +751,7 @@ nsWindow::GetDefaultScaleInternal()
|
||||
if (dpi < 200.0) {
|
||||
return 1.0; // mdpi devices.
|
||||
}
|
||||
if (dpi < 300.0) {
|
||||
if (dpi < 280.0) {
|
||||
return 1.5; // hdpi devices.
|
||||
}
|
||||
// xhdpi devices and beyond.
|
||||
|
||||
@@ -1737,6 +1737,15 @@ nsWindow::GetNativeData(uint32_t aDataType)
|
||||
return (void *) GDK_WINDOW_XID(gdk_window_get_toplevel(mGdkWindow));
|
||||
case NS_NATIVE_PLUGIN_OBJECT_PTR:
|
||||
return (void *) mPluginNativeWindow;
|
||||
case NS_RAW_NATIVE_IME_CONTEXT:
|
||||
// If IME context isn't available on this widget, we should set |this|
|
||||
// instead of nullptr since if we return nullptr, IMEStateManager
|
||||
// cannot manage composition with TextComposition instance. Although,
|
||||
// this case shouldn't occur.
|
||||
if (NS_WARN_IF(!mIMContext)) {
|
||||
return this;
|
||||
}
|
||||
return mIMContext.get();
|
||||
default:
|
||||
NS_WARNING("nsWindow::GetNativeData called with bad value");
|
||||
return nullptr;
|
||||
@@ -6170,13 +6179,8 @@ nsWindow::GetInputContext()
|
||||
if (!mIMContext) {
|
||||
context.mIMEState.mEnabled = IMEState::DISABLED;
|
||||
context.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
|
||||
// If IME context isn't available on this widget, we should set |this|
|
||||
// instead of nullptr since nullptr means that the platform has only one
|
||||
// context per process.
|
||||
context.mNativeIMEContext = this;
|
||||
} else {
|
||||
context = mIMContext->GetInputContext();
|
||||
context.mNativeIMEContext = mIMContext;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#include "mozilla/layers/ChromeProcessController.h"
|
||||
#include "mozilla/layers/InputAPZContext.h"
|
||||
#include "mozilla/layers/APZCCallbackHelper.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Services.h"
|
||||
@@ -86,6 +87,7 @@ static nsRefPtrHashtable<nsVoidPtrHashKey, nsIWidget>* sPluginWidgetList;
|
||||
|
||||
nsIRollupListener* nsBaseWidget::gRollupListener = nullptr;
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::ipc;
|
||||
using namespace mozilla::widget;
|
||||
@@ -2057,9 +2059,49 @@ nsIWidget::SnapshotWidgetOnScreen()
|
||||
return dt->Snapshot();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsIWidget::NativeIMEContext)
|
||||
nsIWidget::GetNativeIMEContext()
|
||||
{
|
||||
return NativeIMEContext(this);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
void
|
||||
NativeIMEContext::Init(nsIWidget* aWidget)
|
||||
{
|
||||
if (!aWidget) {
|
||||
mRawNativeIMEContext = reinterpret_cast<uintptr_t>(nullptr);
|
||||
mOriginProcessID = static_cast<uint64_t>(-1);
|
||||
return;
|
||||
}
|
||||
if (!XRE_IsContentProcess()) {
|
||||
mRawNativeIMEContext = reinterpret_cast<uintptr_t>(
|
||||
aWidget->GetNativeData(NS_RAW_NATIVE_IME_CONTEXT));
|
||||
mOriginProcessID = 0;
|
||||
return;
|
||||
}
|
||||
// If this is created in a child process, aWidget is an instance of
|
||||
// PuppetWidget which doesn't support NS_RAW_NATIVE_IME_CONTEXT.
|
||||
// Instead of that PuppetWidget::GetNativeIMEContext() returns cached
|
||||
// native IME context of the parent process.
|
||||
*this = aWidget->GetNativeIMEContext();
|
||||
}
|
||||
|
||||
void
|
||||
NativeIMEContext::InitWithRawNativeIMEContext(void* aRawNativeIMEContext)
|
||||
{
|
||||
if (NS_WARN_IF(!aRawNativeIMEContext)) {
|
||||
mRawNativeIMEContext = reinterpret_cast<uintptr_t>(nullptr);
|
||||
mOriginProcessID = static_cast<uint64_t>(-1);
|
||||
return;
|
||||
}
|
||||
mRawNativeIMEContext = reinterpret_cast<uintptr_t>(aRawNativeIMEContext);
|
||||
mOriginProcessID =
|
||||
XRE_IsContentProcess() ? ContentChild::GetSingleton()->GetID() : 0;
|
||||
}
|
||||
|
||||
void
|
||||
IMENotification::TextChangeDataBase::MergeWith(
|
||||
const IMENotification::TextChangeDataBase& aOther)
|
||||
|
||||
@@ -544,6 +544,7 @@ struct ParamTraits<mozilla::WidgetCompositionEvent>
|
||||
{
|
||||
WriteParam(aMsg, static_cast<mozilla::WidgetGUIEvent>(aParam));
|
||||
WriteParam(aMsg, aParam.mData);
|
||||
WriteParam(aMsg, aParam.mNativeIMEContext);
|
||||
bool hasRanges = !!aParam.mRanges;
|
||||
WriteParam(aMsg, hasRanges);
|
||||
if (hasRanges) {
|
||||
@@ -557,6 +558,7 @@ struct ParamTraits<mozilla::WidgetCompositionEvent>
|
||||
if (!ReadParam(aMsg, aIter,
|
||||
static_cast<mozilla::WidgetGUIEvent*>(aResult)) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mData) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mNativeIMEContext) ||
|
||||
!ReadParam(aMsg, aIter, &hasRanges)) {
|
||||
return false;
|
||||
}
|
||||
@@ -681,6 +683,24 @@ struct ParamTraits<nsIMEUpdatePreference>
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::widget::NativeIMEContext>
|
||||
{
|
||||
typedef mozilla::widget::NativeIMEContext paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mRawNativeIMEContext);
|
||||
WriteParam(aMsg, aParam.mOriginProcessID);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return ReadParam(aMsg, aIter, &aResult->mRawNativeIMEContext) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mOriginProcessID);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::widget::IMENotification::Point>
|
||||
{
|
||||
|
||||
+16
-1
@@ -103,7 +103,14 @@ typedef void* nsNativeWidget;
|
||||
#define NS_NATIVE_SHAREABLE_WINDOW 11
|
||||
#define NS_NATIVE_OPENGL_CONTEXT 12
|
||||
// See RegisterPluginWindowForRemoteUpdates
|
||||
#define NS_NATIVE_PLUGIN_ID 13
|
||||
#define NS_NATIVE_PLUGIN_ID 13
|
||||
// This is available only with GetNativeData() in parent process. Anybody
|
||||
// shouldn't access this pointer as a valid pointer since the result may be
|
||||
// special value like NS_ONLY_ONE_NATIVE_IME_CONTEXT. So, the result is just
|
||||
// an identifier of distinguishing a text composition is caused by which native
|
||||
// IME context. Note that the result is only valid in the process. So,
|
||||
// XP code should use nsIWidget::GetNativeIMEContext() instead of using this.
|
||||
#define NS_RAW_NATIVE_IME_CONTEXT 14
|
||||
#ifdef XP_MACOSX
|
||||
#define NS_NATIVE_PLUGIN_PORT_QD 100
|
||||
#define NS_NATIVE_PLUGIN_PORT_CG 101
|
||||
@@ -328,6 +335,7 @@ class nsIWidget : public nsISupports {
|
||||
typedef mozilla::widget::IMEState IMEState;
|
||||
typedef mozilla::widget::InputContext InputContext;
|
||||
typedef mozilla::widget::InputContextAction InputContextAction;
|
||||
typedef mozilla::widget::NativeIMEContext NativeIMEContext;
|
||||
typedef mozilla::widget::SizeConstraints SizeConstraints;
|
||||
typedef mozilla::widget::TextEventDispatcher TextEventDispatcher;
|
||||
typedef mozilla::CompositorVsyncDispatcher CompositorVsyncDispatcher;
|
||||
@@ -1763,6 +1771,13 @@ public:
|
||||
*/
|
||||
NS_IMETHOD_(InputContext) GetInputContext() = 0;
|
||||
|
||||
/**
|
||||
* Get native IME context. This is different from GetNativeData() with
|
||||
* NS_RAW_NATIVE_IME_CONTEXT, the result is unique even if in a remote
|
||||
* process.
|
||||
*/
|
||||
NS_IMETHOD_(NativeIMEContext) GetNativeIMEContext();
|
||||
|
||||
/*
|
||||
* Given a WidgetKeyboardEvent, this method synthesizes a corresponding
|
||||
* native (OS-level) event for it. This method allows tests to simulate
|
||||
|
||||
@@ -664,6 +664,10 @@ nsWindow::GetNativeData(uint32_t aDataType)
|
||||
case NS_NATIVE_SHELLWIDGET: {
|
||||
break;
|
||||
}
|
||||
case NS_RAW_NATIVE_IME_CONTEXT:
|
||||
// Our qt widget looks like using only one context per process.
|
||||
// However, it's better to set the context's pointer.
|
||||
return qApp->inputMethod();
|
||||
default:
|
||||
NS_WARNING("nsWindow::GetNativeData called with bad value");
|
||||
return nullptr;
|
||||
@@ -716,10 +720,6 @@ NS_IMETHODIMP_(InputContext)
|
||||
nsWindow::GetInputContext()
|
||||
{
|
||||
mInputContext.mIMEState.mOpen = IMEState::OPEN_STATE_NOT_SUPPORTED;
|
||||
// Our qt widget looks like using only one context per process.
|
||||
// However, it's better to set the context's pointer.
|
||||
mInputContext.mNativeIMEContext = qApp->inputMethod();
|
||||
|
||||
return mInputContext;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user