Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2014-01-14 16:02:20 +01:00
commit 33ad3c995d
35 changed files with 655 additions and 281 deletions

View File

@ -1,4 +1,4 @@
{
"revision": "449764bc60bafa78cec7aa6cad0d65e558ab7473",
"revision": "c8716b0dcb8cc8946903355c3533481f967b52d3",
"repo_path": "/integration/gaia-central"
}

View File

@ -0,0 +1,35 @@
{
"config_version": 2,
"tooltool_manifest": "releng-wasabi.tt",
"mock_target": "mozilla-centos6-i386",
"mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel", "java-1.6.0-openjdk-devel", "git"],
"mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
"build_targets": [],
"upload_files": [
"{objdir}/dist/b2g-*.crashreporter-symbols.zip",
"{objdir}/dist/b2g-*.tar.gz",
"{workdir}/sources.xml"
],
"zip_files": [
["{workdir}/out/target/product/wasabi/*.img", "out/target/product/wasabi/"],
["{workdir}/boot.img", "out/target/product/wasabi/"],
"{workdir}/flash.sh",
"{workdir}/load-config.sh",
"{workdir}/.config",
"{workdir}/sources.xml"
],
"env": {
"VARIANT": "user",
"MOZILLA_OFFICIAL": "1"
},
"b2g_manifest": "wasabi.xml",
"b2g_manifest_branch": "master",
"additional_source_tarballs": ["backup-wasabi.tar.gz"],
"gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
"gaia": {
"l10n": {
"vcs": "hgtool",
"root": "http://hg.mozilla.org/gaia-l10n"
}
}
}

View File

@ -0,0 +1,20 @@
[
{
"size": 311696844,
"digest": "110d6a8a275fb8427816e748448930bb5e6fc45eaba88ac5be824d2873d2d41e1b5c0252d68a1d3b197ec209a7d6dcd1b5e83322702667c8e1b89f3db2ff0bc6",
"algorithm": "sha512",
"filename": "backup-wasabi.tar.gz"
},
{
"size": 1570553,
"digest": "ea03de74df73b05e939c314cd15c54aac7b5488a407b7cc4f5f263f3049a1f69642c567dd35c43d0bc3f0d599d0385a26ab2dd947a6b18f9044e4918b382eea7",
"algorithm": "sha512",
"filename": "Adreno200-AU_LINUX_ANDROID_ICS_CHOCO_CS.04.00.03.06.001.zip"
},
{
"size": 5730304,
"digest": "709a281438607f10c9f55683303d5cc1d8720520e26a8ae45f48b7ccb9265ba8939c4a077ae3368afc891bbd7426013edfbbbb3dbdeab5b1f06e60901b141de6",
"algorithm": "sha512",
"filename": "boot.img"
}
]

View File

@ -53,7 +53,8 @@ pref("apz.axis_lock_mode", 2);
pref("apz.cross_slide.enabled", true);
// Enable Microsoft TSF support by default for imes.
pref("intl.enable_tsf_support", true);
pref("intl.tsf.enable", true);
pref("intl.tsf.support_imm", false);
pref("general.autoScroll", true);
pref("general.smoothScroll", true);

View File

@ -7048,8 +7048,10 @@ dnl We need to wrap dlopen and related functions on Android because we use
dnl our own linker.
if test "$OS_TARGET" = Android; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -L$_objdir/dist/lib -lmozglue"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=PR_GetEnv,--wrap=PR_SetEnv"
if test -z "$gonkdir" -o "$ANDROID_VERSION" -le 18; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=getaddrinfo,--wrap=freeaddrinfo,--wrap=gai_strerror"
fi
if test -z "$gonkdir"; then
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=fork,--wrap=pthread_atfork,--wrap=raise"
WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=memccpy,--wrap=memchr,--wrap=memrchr,--wrap=memcmp,--wrap=memcpy,--wrap=memmove,--wrap=memset,--wrap=memmem,--wrap=memswap,--wrap=index,--wrap=strchr,--wrap=strrchr,--wrap=strlen,--wrap=strcmp,--wrap=strcpy,--wrap=strcat,--wrap=strcasecmp,--wrap=strncasecmp,--wrap=strstr,--wrap=strcasestr,--wrap=strtok,--wrap=strtok_r,--wrap=strerror,--wrap=strerror_r,--wrap=strnlen,--wrap=strncat,--wrap=strncmp,--wrap=strncpy,--wrap=strlcat,--wrap=strlcpy,--wrap=strcspn,--wrap=strpbrk,--wrap=strsep,--wrap=strspn,--wrap=strcoll,--wrap=strxfrm"

View File

@ -1900,6 +1900,12 @@ MediaStream::ChangeExplicitBlockerCount(int32_t aDelta)
}
int32_t mDelta;
};
// This can happen if this method has been called asynchronously, and the
// stream has been destroyed since then.
if (mMainThreadDestroyed) {
return;
}
GraphImpl()->AppendMessage(new Message(this, aDelta));
}

View File

@ -1763,7 +1763,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
if (tmp->mApplicationCache) {
static_cast<nsDOMOfflineResourceList*>(tmp->mApplicationCache.get())->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplicationCache)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentPrincipal)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDoc)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleService)

View File

@ -0,0 +1,29 @@
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_bluetooth_bluetoothhfpmanagerbase_h__
#define mozilla_dom_bluetooth_bluetoothhfpmanagerbase_h__
#include "BluetoothProfileManagerBase.h"
BEGIN_BLUETOOTH_NAMESPACE
class BluetoothHfpManagerBase : public BluetoothProfileManagerBase
{
public:
/**
* Returns true if Sco is connected.
*/
virtual bool IsScoConnected() = 0;
};
#define BT_DECL_HFP_MGR_BASE \
BT_DECL_PROFILE_MGR_BASE \
virtual bool IsScoConnected() MOZ_OVERRIDE;
END_BLUETOOTH_NAMESPACE
#endif //#ifndef mozilla_dom_bluetooth_bluetoothhfpmanagerbase_h__

View File

@ -11,7 +11,7 @@
#include <hardware/bt_hf.h>
#include "BluetoothCommon.h"
#include "BluetoothProfileManagerBase.h"
#include "BluetoothHfpManagerBase.h"
#include "BluetoothRilListener.h"
#include "BluetoothSocketObserver.h"
#include "mozilla/ipc/UnixSocket.h"
@ -71,13 +71,13 @@ public:
bthf_call_addrtype_t mType;
};
class BluetoothHfpManager : public BluetoothProfileManagerBase
class BluetoothHfpManager : public BluetoothHfpManagerBase
, public BatteryObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
BT_DECL_PROFILE_MGR_BASE
BT_DECL_HFP_MGR_BASE
virtual void GetName(nsACString& aName)
{
aName.AssignLiteral("HFP/HSP");
@ -88,7 +88,6 @@ public:
bool ConnectSco();
bool DisconnectSco();
bool IsScoConnected();
/**
* @param aSend A boolean indicates whether we need to notify headset or not

View File

@ -8,7 +8,7 @@
#define mozilla_dom_bluetooth_bluetoothhfpmanager_h__
#include "BluetoothCommon.h"
#include "BluetoothProfileManagerBase.h"
#include "BluetoothHfpManagerBase.h"
#ifdef MOZ_B2G_RIL
#include "BluetoothRilListener.h"
#endif
@ -75,13 +75,13 @@ public:
#endif // MOZ_B2G_RIL
class BluetoothHfpManager : public BluetoothSocketObserver
, public BluetoothProfileManagerBase
, public BluetoothHfpManagerBase
, public BatteryObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
BT_DECL_PROFILE_MGR_BASE
BT_DECL_HFP_MGR_BASE
virtual void GetName(nsACString& aName)
{
aName.AssignLiteral("HFP/HSP");
@ -114,7 +114,6 @@ public:
bool ConnectSco(BluetoothReplyRunnable* aRunnable = nullptr);
bool DisconnectSco();
bool ListenSco();
bool IsScoConnected();
#ifdef MOZ_B2G_RIL
/**

View File

@ -31,8 +31,7 @@
#include "base/message_loop.h"
#include "BluetoothCommon.h"
#include "BluetoothProfileManagerBase.h"
#include "BluetoothHfpManager.h"
#include "BluetoothHfpManagerBase.h"
#include "nsJSUtils.h"
#include "nsCxPusher.h"
@ -230,8 +229,8 @@ AudioManager::HandleBluetoothStatusChanged(nsISupports* aSubject,
#ifdef MOZ_B2G_BT
bool status;
if (!strcmp(aTopic, BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
BluetoothHfpManager* hfp =
static_cast<BluetoothHfpManager*>(aSubject);
BluetoothHfpManagerBase* hfp =
static_cast<BluetoothHfpManagerBase*>(aSubject);
status = hfp->IsScoConnected();
} else {
BluetoothProfileManagerBase* profile =

View File

@ -694,7 +694,27 @@ function RadioInterfaceLayer() {
let options = {
debug: debugPref,
cellBroadcastDisabled: false,
clirMode: RIL.CLIR_DEFAULT
clirMode: RIL.CLIR_DEFAULT,
quirks: {
callstateExtraUint32:
libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
v5Legacy:
libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true",
requestUseDialEmergencyCall:
libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
simAppStateExtraFields:
libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true",
extraUint2ndCall:
libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") == "true",
haveQueryIccLockRetryCount:
libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true",
sendStkProfileDownload:
libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
dataRegistrationOnDemand:
libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true"
},
rilEmergencyNumbers: libcutils.property_get("ril.ecclist") ||
libcutils.property_get("ro.ril.ecclist")
};
try {
@ -1437,6 +1457,17 @@ RadioInterface.prototype = {
this.clientId, message);
break;
case "datacallstatechange":
message.ip = null;
message.netmask = null;
message.broadcast = null;
if (message.ipaddr) {
message.ip = message.ipaddr.split("/")[0];
let ip_value = netHelpers.stringToIP(message.ip);
let prefix_len = message.ipaddr.split("/")[1];
let mask_value = netHelpers.makeMask(prefix_len);
message.netmask = netHelpers.ipToString(mask_value);
message.broadcast = netHelpers.ipToString((ip_value & mask_value) + ~mask_value);
}
this.handleDataCallState(message);
break;
case "datacalllist":

View File

@ -100,16 +100,6 @@ if CONFIG['MOZ_NFC']:
'nfc_worker.js',
]
# include different BluetoothHfpManager.h under dom/bluetooth/
if CONFIG['MOZ_B2G_BT_BLUEZ']:
LOCAL_INCLUDES += [
'/dom/bluetooth/bluez',
]
elif CONFIG['MOZ_B2G_BT_BLUEDROID']:
LOCAL_INCLUDES += [
'/dom/bluetooth/bluedroid',
]
FAIL_ON_WARNINGS = True
include('/ipc/chromium/chromium-config.mozbuild')

View File

@ -38,7 +38,7 @@
"use strict";
importScripts("ril_consts.js", "systemlibs.js");
importScripts("ril_consts.js");
importScripts("resource://gre/modules/workers/require.js");
// set to true in ril_consts.js to see debug messages
@ -53,6 +53,7 @@ if (!this.debug) {
};
}
let RIL_EMERGENCY_NUMBERS;
const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
// Timeout value for emergency callback mode.
@ -74,23 +75,22 @@ const MMI_MAX_LENGTH_SHORT_CODE = 2;
const MMI_END_OF_USSD = "#";
let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true";
let RILQUIRKS_CALLSTATE_EXTRA_UINT32;
// This may change at runtime since in RIL v6 and later, we get the version
// number via the UNSOLICITED_RIL_CONNECTED parcel.
let RILQUIRKS_V5_LEGACY = libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true";
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true";
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = libcutils.property_get("ro.moz.ril.simstate_extra_field", "false") === "true";
let RILQUIRKS_V5_LEGACY;
let RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL;
let RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS;
// Needed for call-waiting on Peak device
let RILQUIRKS_EXTRA_UINT32_2ND_CALL = libcutils.property_get("ro.moz.ril.extra_int_2nd_call", "false") == "true";
let RILQUIRKS_EXTRA_UINT32_2ND_CALL;
// On the emulator we support querying the number of lock retries
let RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = libcutils.property_get("ro.moz.ril.query_icc_count", "false") == "true";
let RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT;
// Ril quirk to Send STK Profile Download
let RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true";
let RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD;
// Ril quirk to attach data registration on demand.
let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND =
libcutils.property_get("ro.moz.ril.data_reg_on_demand", "false") == "true";
let RILQUIRKS_DATA_REGISTRATION_ON_DEMAND;
// Marker object.
let PENDING_NETWORK_TYPE = {};
@ -111,7 +111,7 @@ let Buf = {
// Maps tokens we send out with requests to the request type, so that
// when we get a response parcel back, we know what request it was for.
this.mTokenRequestMap = {};
this.mTokenRequestMap = new Map();
},
/**
@ -125,7 +125,7 @@ let Buf = {
let token = this.readInt32();
let error = this.readInt32();
options = this.mTokenRequestMap[token];
options = this.mTokenRequestMap.get(token);
if (!options) {
if (DEBUG) {
debug("Suspicious uninvited request found: " + token + ". Ignored!");
@ -133,7 +133,7 @@ let Buf = {
return;
}
delete this.mTokenRequestMap[token];
this.mTokenRequestMap.delete(token);
request_type = options.rilRequestType;
options.rilRequestError = error;
@ -174,7 +174,7 @@ let Buf = {
}
options.rilRequestType = type;
options.rilRequestError = null;
this.mTokenRequestMap[this.mToken] = options;
this.mTokenRequestMap.set(this.mToken, options);
this.mToken++;
return this.mToken;
},
@ -2912,12 +2912,8 @@ let RIL = {
* The number to look up.
*/
_isEmergencyNumber: function(number) {
// Check read-write ecclist property first.
let numbers = libcutils.property_get("ril.ecclist");
if (!numbers) {
// Then read-only ecclist property since others RIL only uses this.
numbers = libcutils.property_get("ro.ril.ecclist");
}
// Check ril provided numbers first.
let numbers = RIL_EMERGENCY_NUMBERS;
if (numbers) {
numbers = numbers.split(",");
@ -3585,11 +3581,8 @@ let RIL = {
}
// Set flag for outgoing emergency call.
if (newCall.isOutgoing && this._isEmergencyNumber(newCall.number)) {
newCall.isEmergency = true;
} else {
newCall.isEmergency = false;
}
newCall.isEmergency = newCall.isOutgoing &&
this._isEmergencyNumber(newCall.number);
// Add to our map.
if (newCall.isMpty) {
@ -4962,6 +4955,16 @@ let RIL = {
CLIENT_ID = options.clientId;
this.cellBroadcastDisabled = options.cellBroadcastDisabled;
this.clirMode = options.clirMode;
RIL_EMERGENCY_NUMBERS = options.rilEmergencyNumbers;
let quirks = options.quirks;
RILQUIRKS_CALLSTATE_EXTRA_UINT32 = quirks.callstateExtraUint32;
RILQUIRKS_V5_LEGACY = quirks.v5Legacy;
RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = quirks.requestUseDialEmergencyCall;
RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = quirks.simAppStateExtraFields;
RILQUIRKS_EXTRA_UINT32_2ND_CALL = quirks.extraUint2ndCall;
RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
}
};
@ -5790,7 +5793,7 @@ RIL[REQUEST_QUERY_CLIP] = function(length, options) {
};
RIL[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
RIL.readDataCall_v5 = function readDataCall_v5(options) {
RIL.readDataCall_v5 = function(options) {
if (!options) {
options = {};
}
@ -5802,7 +5805,7 @@ RIL.readDataCall_v5 = function readDataCall_v5(options) {
return options;
};
RIL.readDataCall_v6 = function readDataCall_v6(options) {
RIL.readDataCall_v6 = function(options) {
if (!options) {
options = {};
}
@ -5825,17 +5828,6 @@ RIL.readDataCall_v6 = function readDataCall_v6(options) {
if (options.gw) {
options.gw = options.gw.split(" ")[0];
}
options.ip = null;
options.netmask = null;
options.broadcast = null;
if (options.ipaddr) {
options.ip = options.ipaddr.split("/")[0];
let ip_value = netHelpers.stringToIP(options.ip);
let prefix_len = options.ipaddr.split("/")[1];
let mask_value = netHelpers.makeMask(prefix_len);
options.netmask = netHelpers.ipToString(mask_value);
options.broadcast = netHelpers.ipToString((ip_value & mask_value) + ~mask_value);
}
return options;
};

View File

@ -144,6 +144,19 @@ gfxAndroidPlatform::CreateOffscreenSurface(const gfxIntSize& size,
return newSurface.forget();
}
already_AddRefed<gfxASurface>
gfxAndroidPlatform::OptimizeImage(gfxImageSurface *aSurface,
gfxImageFormat format)
{
/* Android/Gonk have no special offscreen surfaces so we can avoid a copy */
if (OptimalFormatForContent(gfxASurface::ContentFromFormat(format)) ==
format) {
return nullptr;
}
return gfxPlatform::OptimizeImage(aSurface, format);
}
static bool
IsJapaneseLocale()
{

View File

@ -35,6 +35,9 @@ public:
virtual already_AddRefed<gfxASurface>
CreateOffscreenSurface(const gfxIntSize& size,
gfxContentType contentType);
virtual already_AddRefed<gfxASurface>
OptimizeImage(gfxImageSurface *aSurface,
gfxImageFormat format) MOZ_OVERRIDE;
virtual gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }

View File

@ -2150,6 +2150,10 @@ jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
if (!script->compileAndGo() || !script->canBaselineCompile())
return true;
static const uint32_t MAX_SCRIPT_SIZE = 2000;
if (script->length() > MAX_SCRIPT_SIZE)
return true;
Vector<PropertyName *> accessedProperties(cx);
LifoAlloc alloc(types::TypeZone::TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);

View File

@ -15,7 +15,7 @@
# include "jemalloc_types.h"
# ifdef __linux__
# if defined(__linux__) || (defined(MOZ_MEMORY_ANDROID) && (ANDROID_VERSION < 19))
typedef void * usable_ptr_t;
# else
typedef const void * usable_ptr_t;

View File

@ -2698,137 +2698,85 @@ RETURN:
#else /* ! (defined(MOZ_MEMORY_WINDOWS) || defined(JEMALLOC_USES_MAP_ALIGN) || defined(MALLOC_PAGEFILE)) */
/*
* Used by chunk_alloc_mmap() to decide whether to attempt the fast path and
* potentially avoid some system calls.
*/
#ifndef NO_TLS
static __thread bool mmap_unaligned_tls __attribute__((tls_model("initial-exec")));
#define MMAP_UNALIGNED_GET() mmap_unaligned_tls
#define MMAP_UNALIGNED_SET(v) do { \
mmap_unaligned_tls = (v); \
} while (0)
#else
#define NEEDS_PTHREAD_MMAP_UNALIGNED_TSD
static pthread_key_t mmap_unaligned_tsd;
#define MMAP_UNALIGNED_GET() ((bool)pthread_getspecific(mmap_unaligned_tsd))
#define MMAP_UNALIGNED_SET(v) do { \
pthread_setspecific(mmap_unaligned_tsd, (void *)(v)); \
} while (0)
#endif
/* pages_trim, chunk_alloc_mmap_slow and chunk_alloc_mmap were cherry-picked
* from upstream jemalloc 3.4.1 to fix Mozilla bug 956501. */
/* chunk_alloc_mmap_slow and chunk_alloc_mmap were cherry-picked from upstream
* jemalloc 2.2.3 to fix Mozilla bug 694896, enable jemalloc on Mac 10.7. */
/* Return the offset between a and the nearest aligned address at or below a. */
#define ALIGNMENT_ADDR2OFFSET(a, alignment) \
((size_t)((uintptr_t)(a) & (alignment - 1)))
/* Return the smallest alignment multiple that is >= s. */
#define ALIGNMENT_CEILING(s, alignment) \
(((s) + (alignment - 1)) & (-(alignment)))
static void *
chunk_alloc_mmap_slow(size_t size, bool unaligned)
pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size)
{
void *ret;
size_t offset;
void *ret = (void *)((uintptr_t)addr + leadsize);
/* Beware size_t wrap-around. */
if (size + chunksize <= size)
return (NULL);
assert(alloc_size >= leadsize + size);
size_t trailsize = alloc_size - leadsize - size;
ret = pages_map(NULL, size + chunksize, -1);
if (ret == NULL)
return (NULL);
if (leadsize != 0)
pages_unmap(addr, leadsize);
if (trailsize != 0)
pages_unmap((void *)((uintptr_t)ret + size), trailsize);
return (ret);
}
/* Clean up unneeded leading/trailing space. */
offset = CHUNK_ADDR2OFFSET(ret);
if (offset != 0) {
/* Note that mmap() returned an unaligned mapping. */
unaligned = true;
static void *
chunk_alloc_mmap_slow(size_t size, size_t alignment)
{
void *ret, *pages;
size_t alloc_size, leadsize;
/* Leading space. */
pages_unmap(ret, chunksize - offset);
alloc_size = size + alignment - pagesize;
/* Beware size_t wrap-around. */
if (alloc_size < size)
return (NULL);
do {
pages = pages_map(NULL, alloc_size, -1);
if (pages == NULL)
return (NULL);
leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -
(uintptr_t)pages;
ret = pages_trim(pages, alloc_size, leadsize, size);
} while (ret == NULL);
ret = (void *)((uintptr_t)ret +
(chunksize - offset));
/* Trailing space. */
pages_unmap((void *)((uintptr_t)ret + size),
offset);
} else {
/* Trailing space only. */
pages_unmap((void *)((uintptr_t)ret + size),
chunksize);
}
/*
* If mmap() returned an aligned mapping, reset mmap_unaligned so that
* the next chunk_alloc_mmap() execution tries the fast allocation
* method.
*/
if (unaligned == false)
MMAP_UNALIGNED_SET(false);
return (ret);
assert(ret != NULL);
return (ret);
}
static void *
chunk_alloc_mmap(size_t size, bool pagefile)
{
void *ret;
void *ret;
size_t offset;
/*
* Ideally, there would be a way to specify alignment to mmap() (like
* NetBSD has), but in the absence of such a feature, we have to work
* hard to efficiently create aligned mappings. The reliable, but
* slow method is to create a mapping that is over-sized, then trim the
* excess. However, that always results in at least one call to
* pages_unmap().
*
* A more optimistic approach is to try mapping precisely the right
* amount, then try to append another mapping if alignment is off. In
* practice, this works out well as long as the application is not
* interleaving mappings via direct mmap() calls. If we do run into a
* situation where there is an interleaved mapping and we are unable to
* extend an unaligned mapping, our best option is to switch to the
* slow method until mmap() returns another aligned mapping. This will
* tend to leave a gap in the memory map that is too small to cause
* later problems for the optimistic method.
*
* Another possible confounding factor is address space layout
* randomization (ASLR), which causes mmap(2) to disregard the
* requested address. mmap_unaligned tracks whether the previous
* chunk_alloc_mmap() execution received any unaligned or relocated
* mappings, and if so, the current execution will immediately fall
* back to the slow method. However, we keep track of whether the fast
* method would have succeeded, and if so, we make a note to try the
* fast method next time.
*/
/*
* Ideally, there would be a way to specify alignment to mmap() (like
* NetBSD has), but in the absence of such a feature, we have to work
* hard to efficiently create aligned mappings. The reliable, but
* slow method is to create a mapping that is over-sized, then trim the
* excess. However, that always results in one or two calls to
* pages_unmap().
*
* Optimistically try mapping precisely the right amount before falling
* back to the slow method, with the expectation that the optimistic
* approach works most of the time.
*/
if (MMAP_UNALIGNED_GET() == false) {
size_t offset;
ret = pages_map(NULL, size, -1);
if (ret == NULL)
return (NULL);
offset = ALIGNMENT_ADDR2OFFSET(ret, chunksize);
if (offset != 0) {
pages_unmap(ret, size);
return (chunk_alloc_mmap_slow(size, chunksize));
}
ret = pages_map(NULL, size, -1);
if (ret == NULL)
return (NULL);
offset = CHUNK_ADDR2OFFSET(ret);
if (offset != 0) {
MMAP_UNALIGNED_SET(true);
/* Try to extend chunk boundary. */
if (pages_map((void *)((uintptr_t)ret + size),
chunksize - offset, -1) == NULL) {
/*
* Extension failed. Clean up, then revert to
* the reliable-but-expensive method.
*/
pages_unmap(ret, size);
ret = chunk_alloc_mmap_slow(size, true);
} else {
/* Clean up unneeded leading space. */
pages_unmap(ret, chunksize - offset);
ret = (void *)((uintptr_t)ret + (chunksize -
offset));
}
}
} else
ret = chunk_alloc_mmap_slow(size, false);
return (ret);
assert(ret != NULL);
return (ret);
}
#endif /* defined(MOZ_MEMORY_WINDOWS) || defined(JEMALLOC_USES_MAP_ALIGN) || defined(MALLOC_PAGEFILE) */
@ -6600,7 +6548,7 @@ malloc_good_size_impl(size_t size)
}
#ifdef MOZ_MEMORY_ANDROID
#if defined(MOZ_MEMORY_ANDROID) && (ANDROID_VERSION < 19)
MOZ_MEMORY_API size_t
malloc_usable_size_impl(void *ptr)
#else

View File

@ -2552,7 +2552,10 @@ pref("intl.keyboard.per_window_layout", false);
#ifdef NS_ENABLE_TSF
// Enable/Disable TSF support
pref("intl.enable_tsf_support", false);
pref("intl.tsf.enable", false);
// Support IMEs implemented with IMM in TSF mode.
pref("intl.tsf.support_imm", true);
// We need to notify the layout change to TSF, but we cannot check the actual
// change now, therefore, we always notify it by this fequency.

View File

@ -28,7 +28,8 @@ else:
add_tier_dir('base', ['mfbt'])
if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gonk'):
add_tier_dir('base', ['other-licenses/android'])
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] <= '18':
add_tier_dir('base', ['other-licenses/android'])
if CONFIG['MOZ_MEMORY']:
add_tier_dir('base', ['memory'])

View File

@ -409,7 +409,7 @@ Seer::Init()
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(mDBFile));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBFile->AppendNative(NS_LITERAL_CSTRING("seer.sqlite"));
rv = mDBFile->AppendNative(NS_LITERAL_CSTRING("netpredictions.sqlite"));
NS_ENSURE_SUCCESS(rv, rv);
mInitialized = true;
@ -417,6 +417,25 @@ Seer::Init()
return rv;
}
void
Seer::CheckForAndDeleteOldDBFile()
{
nsCOMPtr<nsIFile> oldDBFile;
nsresult rv = mDBFile->GetParent(getter_AddRefs(oldDBFile));
RETURN_IF_FAILED(rv);
rv = oldDBFile->AppendNative(NS_LITERAL_CSTRING("seer.sqlite"));
RETURN_IF_FAILED(rv);
bool oldFileExists = false;
rv = oldDBFile->Exists(&oldFileExists);
if (NS_FAILED(rv) || !oldFileExists) {
return;
}
oldDBFile->Remove(false);
}
// Make sure that our sqlite storage is all set up with all the tables we need
// to do the work. It isn't the end of the world if this fails, since this is
// all an optimization, anyway.
@ -432,6 +451,8 @@ Seer::EnsureInitStorage()
nsresult rv;
CheckForAndDeleteOldDBFile();
rv = mStorageService->OpenDatabase(mDBFile, getter_AddRefs(mDB));
if (NS_FAILED(rv)) {
// Retry once by trashing the file and trying to open again. If this fails,
@ -668,7 +689,7 @@ Seer::EnsureInitStorage()
" origin TEXT NOT NULL,\n"
" hits INTEGER DEFAULT 0,\n"
" last_hit INTEGER DEFAULT 0,\n"
" FOREIGN KEY(pid) REFERENCES moz_pages(id)\n"
" FOREIGN KEY(pid) REFERENCES moz_pages(id) ON DELETE CASCADE\n"
");\n"));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -62,6 +62,7 @@ private:
friend class SeerPredictionRunner;
friend class SeerDBShutdownRunner;
void CheckForAndDeleteOldDBFile();
nsresult EnsureInitStorage();
// This is a proxy for the information we need from an nsIURI

View File

@ -216,7 +216,7 @@ DnsContinueVerifier.prototype = {
// x1000 on the Date object value.
var tstamp = (new Date().valueOf() * 1000) - (10 * 86400 * 1000000);
var dbfile = FileUtils.getFile("ProfD", ["seer.sqlite"]);
var dbfile = FileUtils.getFile("ProfD", ["netpredictions.sqlite"]);
var dbconn = Services.storage.openDatabase(dbfile);
// We also need to update hits, since the toplevel has been "loaded" a
// second time (from the prediction that kicked off this callback) to ensure

View File

@ -95,6 +95,9 @@
*/
#include "SSLServerCertVerification.h"
#include <cstring>
#include "CertVerifier.h"
#include "nsIBadCertListener2.h"
#include "nsICertOverrideService.h"
@ -633,7 +636,7 @@ class SSLServerCertVerificationJob : public nsRunnable
public:
// Must be called only on the socket transport thread
static SECStatus Dispatch(const void * fdForLogging,
TransportSecurityInfo * infoObject,
nsNSSSocketInfo * infoObject,
CERTCertificate * serverCert,
SECItem * stapledOCSPResponse,
uint32_t providerFlags);
@ -642,12 +645,12 @@ private:
// Must be called only on the socket transport thread
SSLServerCertVerificationJob(const void * fdForLogging,
TransportSecurityInfo * infoObject,
nsNSSSocketInfo * infoObject,
CERTCertificate * cert,
SECItem * stapledOCSPResponse,
uint32_t providerFlags);
const void * const mFdForLogging;
const RefPtr<TransportSecurityInfo> mInfoObject;
const RefPtr<nsNSSSocketInfo> mInfoObject;
const ScopedCERTCertificate mCert;
const uint32_t mProviderFlags;
const TimeStamp mJobStartTime;
@ -655,7 +658,7 @@ private:
};
SSLServerCertVerificationJob::SSLServerCertVerificationJob(
const void * fdForLogging, TransportSecurityInfo * infoObject,
const void * fdForLogging, nsNSSSocketInfo * infoObject,
CERTCertificate * cert, SECItem * stapledOCSPResponse,
uint32_t providerFlags)
: mFdForLogging(fdForLogging)
@ -855,7 +858,7 @@ BlockServerCertChangeForSpdy(nsNSSSocketInfo *infoObject,
}
SECStatus
AuthCertificate(TransportSecurityInfo * infoObject, CERTCertificate * cert,
AuthCertificate(nsNSSSocketInfo * infoObject, CERTCertificate * cert,
SECItem * stapledOCSPResponse, uint32_t providerFlags)
{
if (cert->serialNumber.data &&
@ -923,6 +926,25 @@ AuthCertificate(TransportSecurityInfo * infoObject, CERTCertificate * cert,
} else {
// no stapled OCSP response
Telemetry::Accumulate(Telemetry::SSL_OCSP_STAPLING, 2);
uint32_t reasonsForNotFetching = 0;
char* ocspURI = CERT_GetOCSPAuthorityInfoAccessLocation(cert);
if (!ocspURI) {
reasonsForNotFetching |= 1; // invalid/missing OCSP URI
} else {
if (std::strncmp(ocspURI, "http://", 7)) { // approximation
reasonsForNotFetching |= 1; // invalid/missing OCSP URI
}
PORT_Free(ocspURI);
}
if (!infoObject->SharedState().IsOCSPFetchingEnabled()) {
reasonsForNotFetching |= 2;
}
Telemetry::Accumulate(Telemetry::SSL_OCSP_MAY_FETCH,
reasonsForNotFetching);
}
CERTCertList *verifyCertChain = nullptr;
@ -1044,7 +1066,7 @@ AuthCertificate(TransportSecurityInfo * infoObject, CERTCertificate * cert,
/*static*/ SECStatus
SSLServerCertVerificationJob::Dispatch(const void * fdForLogging,
TransportSecurityInfo * infoObject,
nsNSSSocketInfo * infoObject,
CERTCertificate * serverCert,
SECItem * stapledOCSPResponse,
uint32_t providerFlags)

View File

@ -136,6 +136,7 @@ SharedSSLState::SharedSSLState()
, mMutex("SharedSSLState::mMutex")
, mSocketCreated(false)
, mOCSPStaplingEnabled(false)
, mOCSPFetchingEnabled(false)
{
mIOLayerHelpers.Init();
mClientAuthRemember->Init();

View File

@ -36,7 +36,11 @@ public:
// Main-thread only
void ResetStoredData();
void NotePrivateBrowsingStatus();
void SetOCSPStaplingEnabled(bool enabled) { mOCSPStaplingEnabled = enabled; }
void SetOCSPOptions(bool fetchingEnabled, bool staplingEnabled)
{
mOCSPFetchingEnabled = fetchingEnabled;
mOCSPStaplingEnabled = staplingEnabled;
}
// The following methods may be called from any thread
bool SocketCreated();
@ -44,6 +48,7 @@ public:
static void NoteCertOverrideServiceInstantiated();
static void NoteCertDBServiceInstantiated();
bool IsOCSPStaplingEnabled() const { return mOCSPStaplingEnabled; }
bool IsOCSPFetchingEnabled() const { return mOCSPFetchingEnabled; }
private:
void Cleanup();
@ -58,6 +63,7 @@ private:
Mutex mMutex;
bool mSocketCreated;
bool mOCSPStaplingEnabled;
bool mOCSPFetchingEnabled;
};
SharedSSLState* PublicSSLState();

View File

@ -1001,11 +1001,15 @@ void nsNSSComponent::setValidationOptions(bool isInitialSetting)
bool crlDownloading = Preferences::GetBool("security.CRL_download.enabled",
false);
// This preference controls whether we do OCSP fetching and does not affect
// OCSP stapling.
// 0 = disabled, 1 = enabled
int32_t ocspEnabled = Preferences::GetInt("security.OCSP.enabled",
OCSP_ENABLED_DEFAULT);
bool ocspRequired = Preferences::GetBool("security.OCSP.require", false);
bool ocspRequired = ocspEnabled &&
Preferences::GetBool("security.OCSP.require", false);
// We measure the setting of the pref at startup only to minimize noise by
// addons that may muck with the settings, though it probably doesn't matter.
@ -1019,11 +1023,8 @@ void nsNSSComponent::setValidationOptions(bool isInitialSetting)
bool ocspStaplingEnabled = Preferences::GetBool("security.ssl.enable_ocsp_stapling",
true);
if (!ocspEnabled) {
ocspStaplingEnabled = false;
}
PublicSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
PrivateSSLState()->SetOCSPStaplingEnabled(ocspStaplingEnabled);
PublicSSLState()->SetOCSPOptions(ocspEnabled, ocspStaplingEnabled);
PrivateSSLState()->SetOCSPOptions(ocspEnabled, ocspStaplingEnabled);
setNonPkixOcspEnabled(ocspEnabled);

View File

@ -5584,6 +5584,12 @@
"n_values": 8,
"description": "Status of OCSP stapling on this handshake (1=present, good; 2=none; 3=present, expired; 4=present, other error)"
},
"SSL_OCSP_MAY_FETCH": {
"expires_in_version": "never",
"kind": "enumerated",
"n_values": 8,
"description": "For non-stapling cases, is OCSP fetching a possibility? (0=yes, 1=no because missing/invalid OCSP URI, 2=no because fetching disabled, 3=no because both)"
},
"TELEMETRY_TEST_EXPIRED": {
"expires_in_version": "4.0a1",
"kind": "flag",

View File

@ -954,8 +954,8 @@ mFailedLockCount(0)
const char *trackedDBs[] = {
"addons.sqlite", "content-prefs.sqlite", "cookies.sqlite",
"downloads.sqlite", "extensions.sqlite", "formhistory.sqlite",
"index.sqlite", "healthreport.sqlite", "permissions.sqlite",
"places.sqlite", "search.sqlite", "seer.sqlite", "signons.sqlite",
"index.sqlite", "healthreport.sqlite", "netpredictions.sqlite",
"permissions.sqlite", "places.sqlite", "search.sqlite", "signons.sqlite",
"urlclassifier3.sqlite", "webappsstore.sqlite"
};

View File

@ -4,6 +4,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WinIMEHandler.h"
#include "mozilla/Preferences.h"
#include "nsIMM32Handler.h"
#include "nsWindowDefs.h"
@ -23,6 +25,7 @@ namespace widget {
#ifdef NS_ENABLE_TSF
bool IMEHandler::sIsInTSFMode = false;
bool IMEHandler::sIsIMMEnabled = true;
bool IMEHandler::sPluginHasFocus = false;
IMEHandler::SetInputScopesFunc IMEHandler::sSetInputScopes = nullptr;
#endif // #ifdef NS_ENABLE_TSF
@ -34,6 +37,8 @@ IMEHandler::Initialize()
#ifdef NS_ENABLE_TSF
nsTextStore::Initialize();
sIsInTSFMode = nsTextStore::IsInTSFMode();
sIsIMMEnabled =
!sIsInTSFMode || Preferences::GetBool("intl.tsf.support_imm", true);
if (!sIsInTSFMode) {
// When full nsTextStore is not available, try to use SetInputScopes API
// to enable at least InputScope. Use GET_MODULE_HANDLE_EX_FLAG_PIN to
@ -104,24 +109,19 @@ IMEHandler::ProcessMessage(nsWindow* aWindow, UINT aMessage,
{
#ifdef NS_ENABLE_TSF
if (IsTSFAvailable()) {
if (aMessage == WM_IME_SETCONTEXT) {
// If a windowless plugin had focus and IME was handled on it, composition
// window was set the position. After that, even in TSF mode, WinXP keeps
// to use composition window at the position if the active IME is not
// aware TSF. For avoiding this issue, we need to hide the composition
// window here.
if (aWParam) {
aLParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
}
return false;
}
if (aMessage == WM_USER_TSF_TEXTCHANGE) {
nsTextStore::OnTextChangeMsg();
aResult.mConsumed = true;
nsTextStore::ProcessMessage(aWindow, aMessage, aWParam, aLParam, aResult);
if (aResult.mConsumed) {
return true;
}
return false;
// If we don't support IMM in TSF mode, we don't use nsIMM32Handler.
if (!sIsIMMEnabled) {
return false;
}
// IME isn't implemented with IMM, nsIMM32Handler shouldn't handle any
// messages.
if (!nsTextStore::IsIMM_IME()) {
return false;
}
}
#endif // #ifdef NS_ENABLE_TSF
@ -264,8 +264,7 @@ IMEHandler::OnDestroyWindow(nsWindow* aWindow)
SetInputScopeForIMM32(aWindow, EmptyString());
}
#endif // #ifdef NS_ENABLE_TSF
nsIMEContext IMEContext(aWindow->GetWindowHandle());
IMEContext.AssociateDefaultContext();
AssociateIMEContext(aWindow, true);
}
// static
@ -277,6 +276,8 @@ IMEHandler::SetInputContext(nsWindow* aWindow,
// FYI: If there is no composition, this call will do nothing.
NotifyIME(aWindow, REQUEST_TO_COMMIT_COMPOSITION);
const InputContext& oldInputContext = aWindow->GetInputContext();
// Assume that SetInputContext() is called only when aWindow has focus.
sPluginHasFocus = (aInputContext.mIMEState.mEnabled == IMEState::PLUGIN);
@ -294,6 +295,14 @@ IMEHandler::SetInputContext(nsWindow* aWindow,
nsTextStore::SetInputContext(aWindow, aInputContext, aAction);
if (IsTSFAvailable()) {
aInputContext.mNativeIMEContext = nsTextStore::GetTextStore();
if (sIsIMMEnabled) {
// Associate IME context for IMM-IMEs.
AssociateIMEContext(aWindow, enable);
} else if (oldInputContext.mIMEState.mEnabled == IMEState::PLUGIN) {
// Disassociate the IME context from the window when plugin loses focus
// in pure TSF mode.
AssociateIMEContext(aWindow, false);
}
if (adjustOpenState) {
nsTextStore::SetIMEOpenState(open);
}
@ -305,25 +314,37 @@ IMEHandler::SetInputContext(nsWindow* aWindow,
}
#endif // #ifdef NS_ENABLE_TSF
nsIMEContext IMEContext(aWindow->GetWindowHandle());
if (enable) {
IMEContext.AssociateDefaultContext();
if (!aInputContext.mNativeIMEContext) {
aInputContext.mNativeIMEContext = static_cast<void*>(IMEContext.get());
}
} else if (!aWindow->Destroyed()) {
// Don't disassociate the context after the window is destroyed.
IMEContext.Disassociate();
if (!aInputContext.mNativeIMEContext) {
// The old InputContext must store the default IMC.
aInputContext.mNativeIMEContext =
aWindow->GetInputContext().mNativeIMEContext;
}
}
AssociateIMEContext(aWindow, enable);
nsIMEContext IMEContext(aWindow->GetWindowHandle());
if (adjustOpenState) {
IMEContext.SetOpenState(open);
}
if (aInputContext.mNativeIMEContext) {
return;
}
// The old InputContext must store the default IMC or old TextStore.
// When IME context is disassociated from the window, use it.
aInputContext.mNativeIMEContext = enable ?
static_cast<void*>(IMEContext.get()) : oldInputContext.mNativeIMEContext;
}
// static
void
IMEHandler::AssociateIMEContext(nsWindow* aWindow, bool aEnable)
{
nsIMEContext IMEContext(aWindow->GetWindowHandle());
if (aEnable) {
IMEContext.AssociateDefaultContext();
return;
}
// Don't disassociate the context after the window is destroyed.
if (aWindow->Destroyed()) {
return;
}
IMEContext.Disassociate();
}
// static
@ -340,6 +361,10 @@ IMEHandler::InitInputContext(nsWindow* aWindow, InputContext& aInputContext)
InputContextAction::GOT_FOCUS));
aInputContext.mNativeIMEContext = nsTextStore::GetTextStore();
MOZ_ASSERT(aInputContext.mNativeIMEContext);
// IME context isn't necessary in pure TSF mode.
if (!sIsIMMEnabled) {
AssociateIMEContext(aWindow, false);
}
return;
}
#endif // #ifdef NS_ENABLE_TSF

View File

@ -100,6 +100,11 @@ public:
InputContext& aInputContext,
const InputContextAction& aAction);
/**
* Associate or disassociate IME context to/from the aWindow.
*/
static void AssociateIMEContext(nsWindow* aWindow, bool aEnable);
/**
* Called when the window is created.
*/
@ -125,6 +130,9 @@ private:
static void SetInputScopeForIMM32(nsWindow* aWindow,
const nsAString& aHTMLInputType);
static bool sIsInTSFMode;
// If sIMMEnabled is false, any IME messages are not handled in TSF mode.
// Additionally, IME context is always disassociated from focused window.
static bool sIsIMMEnabled;
static bool sPluginHasFocus;
static bool IsTSFAvailable() { return (sIsInTSFMode && !sPluginHasFocus); }

View File

@ -28,6 +28,12 @@
using namespace mozilla;
using namespace mozilla::widget;
static const char* kPrefNameTSFEnabled = "intl.tsf.enable";
static const char* kPrefNameLayoutChangeInternal =
"intl.tsf.on_layout_change_interval";
static const char* kLegacyPrefNameTSFEnabled = "intl.enable_tsf_support";
#ifdef PR_LOGGING
/**
* TSF related code should log its behavior even on release build especially
@ -138,6 +144,7 @@ ITfDisplayAttributeMgr* nsTextStore::sDisplayAttrMgr = nullptr;
ITfCategoryMgr* nsTextStore::sCategoryMgr = nullptr;
ITfDocumentMgr* nsTextStore::sTsfDisabledDocumentMgr = nullptr;
ITfContext* nsTextStore::sTsfDisabledContext = nullptr;
ITfInputProcessorProfiles* nsTextStore::sInputProcessorProfiles = nullptr;
DWORD nsTextStore::sTsfClientId = 0;
nsTextStore* nsTextStore::sTsfTextStore = nullptr;
@ -251,6 +258,18 @@ GetCLSIDNameStr(REFCLSID aCLSID)
return result;
}
static nsCString
GetGUIDNameStr(REFGUID aGUID)
{
OLECHAR str[40];
int len = ::StringFromGUID2(aGUID, str, ArrayLength(str));
if (!len || !str[0]) {
return EmptyCString();
}
return NS_ConvertUTF16toUTF8(str);
}
static nsCString
GetRIIDNameStr(REFIID aRIID)
{
@ -500,11 +519,9 @@ GetDisplayAttrStr(const TF_DISPLAYATTRIBUTE &aDispAttr)
nsTextStore::nsTextStore()
: mContent(mComposition, mSelection)
{
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::nsTestStore(): instance is created", this));
mRefCnt = 1;
mEditCookie = 0;
mIPProfileCookie = TF_INVALID_COOKIE;
mSinkMask = 0;
mLock = 0;
mLockQueued = 0;
@ -514,16 +531,91 @@ nsTextStore::nsTextStore()
mInputScopeRequested = false;
mIsRecordingActionsWithoutLock = false;
mNotifySelectionChange = false;
mIsIMM_IME = IsIMM_IME(::GetKeyboardLayout(0));
// We hope that 5 or more actions don't occur at once.
mPendingActions.SetCapacity(5);
// On Vista or later, Windows let us know activate IME changed only with
// ITfInputProcessorProfileActivationSink. However, there is no way to get
// it via TSF on XP. (NOTE: ITfLanguageProfileNotifySink works only when
// keyboard layout is changed to different language. So, its behavior is
// different from WM_INPUTLANGCHANGE on WinXP. On WinXP, the message is
// delivered when active IME is changed without language change.)
if (IsVistaOrLater()) {
nsRefPtr<ITfSource> source;
HRESULT hr =
sTsfThreadMgr->QueryInterface(IID_ITfSource, getter_AddRefs(source));
if (SUCCEEDED(hr)) {
hr = source->AdviseSink(IID_ITfInputProcessorProfileActivationSink,
static_cast<ITfInputProcessorProfileActivationSink*>(this),
&mIPProfileCookie);
#ifdef PR_LOGGING
if (FAILED(hr) || mIPProfileCookie == TF_INVALID_COOKIE) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore FAILED to install "
"ITfInputProcessorProfileActivationSink (0x%08X)", this, hr));
}
} else {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore FAILED to get ITfSource instance "
"(0x%08X)", this, hr));
#endif // #ifdef PR_LOGGING
}
}
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::nsTestStore(): instance is created, "
"mIsIMM_IME=%s, mIPProfileCookie=%08X",
this, GetBoolName(mIsIMM_IME), mIPProfileCookie));
}
nsTextStore::~nsTextStore()
{
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore instance is destroyed, "
"mWidget=0x%p, mDocumentMgr=0x%p, mContext=0x%p",
this, mWidget.get(), mDocumentMgr.get(), mContext.get()));
"mWidget=0x%p, mDocumentMgr=0x%p, mContext=0x%p, mIPProfileCookie=0x%08X",
this, mWidget.get(), mDocumentMgr.get(), mContext.get(),
mIPProfileCookie));
if (mIPProfileCookie != TF_INVALID_COOKIE) {
if (IsVistaOrLater()) {
nsRefPtr<ITfSource> source;
HRESULT hr =
sTsfThreadMgr->QueryInterface(IID_ITfSource, getter_AddRefs(source));
if (FAILED(hr)) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p ~nsTextStore FAILED to get ITfSource instance "
"(0x%08X)", this, hr));
} else {
hr = source->UnadviseSink(mIPProfileCookie);
if (FAILED(hr)) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p ~nsTextStore FAILED to uninstall "
"ITfInputProcessorProfileActivationSink (0x%08X)",
this, hr));
}
}
} else {
nsRefPtr<ITfSource> source;
HRESULT hr =
sInputProcessorProfiles->QueryInterface(IID_ITfSource,
getter_AddRefs(source));
if (FAILED(hr)) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p ~nsTextStore FAILED to get ITfSource instance "
"(0x%08X)", this, hr));
} else {
hr = source->UnadviseSink(mIPProfileCookie);
if (FAILED(hr)) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p ~nsTextStore FAILED to uninstall "
"ITfLanguageProfileNotifySink (0x%08X)",
this, hr));
}
}
NS_RELEASE(sInputProcessorProfiles);
}
}
mComposition.EnsureLayoutChangeTimerStopped();
}
@ -627,6 +719,8 @@ nsTextStore::QueryInterface(REFIID riid,
*ppv = static_cast<ITextStoreACP*>(this);
} else if (IID_ITfContextOwnerCompositionSink == riid) {
*ppv = static_cast<ITfContextOwnerCompositionSink*>(this);
} else if (IID_ITfInputProcessorProfileActivationSink == riid) {
*ppv = static_cast<ITfInputProcessorProfileActivationSink*>(this);
}
if (*ppv) {
AddRef();
@ -2866,6 +2960,34 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
return S_OK;
}
STDMETHODIMP
nsTextStore::OnActivated(DWORD dwProfileType,
LANGID langid,
REFCLSID rclsid,
REFGUID catid,
REFGUID guidProfile,
HKL hkl,
DWORD dwFlags)
{
// NOTE: This is installed only on Vista or later.
if (dwFlags & TF_IPSINK_FLAG_ACTIVE) {
mIsIMM_IME = IsIMM_IME(hkl);
}
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::OnActivated(dwProfileType=%s (0x%08X), "
"langid=0x%08X, rclsid=%s, catid=%s, guidProfile=%s, hkl=0x%08X, "
"dwFlags=0x%08X (TF_IPSINK_FLAG_ACTIVE: %s)), mIsIMM_IME=%s",
this, dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR ?
"TF_PROFILETYPE_INPUTPROCESSOR" :
dwProfileType == TF_PROFILETYPE_KEYBOARDLAYOUT ?
"TF_PROFILETYPE_KEYBOARDLAYOUT" : "Unknown", dwProfileType,
langid, GetCLSIDNameStr(rclsid).get(), GetGUIDNameStr(catid).get(),
GetGUIDNameStr(guidProfile).get(), hkl, dwFlags,
GetBoolName(dwFlags & TF_IPSINK_FLAG_ACTIVE),
GetBoolName(mIsIMM_IME)));
return S_OK;
}
// static
nsresult
nsTextStore::OnFocusChange(bool aGotFocus,
@ -2967,10 +3089,10 @@ nsTextStore::OnTextChangeInternal(uint32_t aStart,
}
void
nsTextStore::OnTextChangeMsgInternal(void)
nsTextStore::OnTextChangeMsg()
{
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::OnTextChangeMsgInternal(), "
("TSF: 0x%p nsTextStore::OnTextChangeMsg(), "
"mSink=0x%p, mSinkMask=%s, mTextChange={ acpStart=%ld, "
"acpOldEnd=%ld, acpNewEnd=%ld }",
this, mSink.get(),
@ -2980,7 +3102,7 @@ nsTextStore::OnTextChangeMsgInternal(void)
if (!mLock && mSink && 0 != (mSinkMask & TS_AS_TEXT_CHANGE) &&
INT32_MAX > mTextChange.acpStart) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::OnTextChangeMsgInternal(), calling"
("TSF: 0x%p nsTextStore::OnTextChangeMsg(), calling"
"mSink->OnTextChange(0, { acpStart=%ld, acpOldEnd=%ld, "
"acpNewEnd=%ld })...", this, mTextChange.acpStart,
mTextChange.acpOldEnd, mTextChange.acpNewEnd));
@ -3242,7 +3364,14 @@ nsTextStore::Initialize(void)
}
#endif
bool enableTsf = Preferences::GetBool("intl.enable_tsf_support", false);
bool enableTsf = Preferences::GetBool(kPrefNameTSFEnabled, false);
// Migrate legacy TSF pref to new pref. This should be removed in next
// release cycle or later.
if (!enableTsf && Preferences::GetBool(kLegacyPrefNameTSFEnabled, false)) {
enableTsf = true;
Preferences::SetBool(kPrefNameTSFEnabled, true);
Preferences::ClearUser(kLegacyPrefNameTSFEnabled);
}
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: nsTextStore::Initialize(), TSF is %s",
enableTsf ? "enabled" : "disabled"));
@ -3250,6 +3379,22 @@ nsTextStore::Initialize(void)
return;
}
// XXX MSDN documents that ITfInputProcessorProfiles is available only on
// desktop apps. However, there is no known way to obtain
// ITfInputProcessorProfileMgr instance without ITfInputProcessorProfiles
// instance.
HRESULT hr =
::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr,
CLSCTX_INPROC_SERVER,
IID_ITfInputProcessorProfiles,
reinterpret_cast<void**>(&sInputProcessorProfiles));
if (FAILED(hr) || !sInputProcessorProfiles) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: nsTextStore::Initialize() FAILED to create input processor "
"profiles"));
return;
}
if (!sTsfThreadMgr) {
if (SUCCEEDED(CoCreateInstance(CLSID_TF_ThreadMgr, nullptr,
CLSCTX_INPROC_SERVER, IID_ITfThreadMgr,
@ -3292,10 +3437,9 @@ nsTextStore::Initialize(void)
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: nsTextStore::Initialize() is creating "
"a display attribute manager instance..."));
HRESULT hr =
::CoCreateInstance(CLSID_TF_DisplayAttributeMgr, nullptr,
CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeMgr,
reinterpret_cast<void**>(&sDisplayAttrMgr));
hr = ::CoCreateInstance(CLSID_TF_DisplayAttributeMgr, nullptr,
CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeMgr,
reinterpret_cast<void**>(&sDisplayAttrMgr));
if (FAILED(hr) || !sDisplayAttrMgr) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: nsTextStore::Initialize() FAILED to create "
@ -3306,10 +3450,9 @@ nsTextStore::Initialize(void)
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: nsTextStore::Initialize() is creating "
"a category manager instance..."));
HRESULT hr =
::CoCreateInstance(CLSID_TF_CategoryMgr, nullptr,
CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr,
reinterpret_cast<void**>(&sCategoryMgr));
hr = ::CoCreateInstance(CLSID_TF_CategoryMgr, nullptr,
CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr,
reinterpret_cast<void**>(&sCategoryMgr));
if (FAILED(hr) || !sCategoryMgr) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: nsTextStore::Initialize() FAILED to create "
@ -3321,8 +3464,7 @@ nsTextStore::Initialize(void)
}
if (sTsfThreadMgr && sTsfTextStore) {
HRESULT hr =
sTsfThreadMgr->CreateDocumentMgr(&sTsfDisabledDocumentMgr);
hr = sTsfThreadMgr->CreateDocumentMgr(&sTsfDisabledDocumentMgr);
if (FAILED(hr) || !sTsfDisabledDocumentMgr) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: nsTextStore::Initialize() FAILED to create "
@ -3374,6 +3516,7 @@ nsTextStore::Terminate(void)
NS_IF_RELEASE(sTsfTextStore);
NS_IF_RELEASE(sTsfDisabledDocumentMgr);
NS_IF_RELEASE(sTsfDisabledContext);
NS_IF_RELEASE(sInputProcessorProfiles);
sTsfClientId = 0;
if (sTsfThreadMgr) {
sTsfThreadMgr->Deactivate();
@ -3412,6 +3555,48 @@ nsTextStore::ProcessRawKeyMessage(const MSG& aMsg)
return false;
}
// static
void
nsTextStore::ProcessMessage(nsWindowBase* aWindow, UINT aMessage,
WPARAM& aWParam, LPARAM& aLParam,
MSGResult& aResult)
{
switch (aMessage) {
case WM_IME_SETCONTEXT:
// If a windowless plugin had focus and IME was handled on it, composition
// window was set the position. After that, even in TSF mode, WinXP keeps
// to use composition window at the position if the active IME is not
// aware TSF. For avoiding this issue, we need to hide the composition
// window here.
if (aWParam) {
aLParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
}
break;
case WM_INPUTLANGCHANGE:
if (IsVistaOrLater()) {
break;
}
// On WinXP, WM_INPUTLANGCHANGE message is the only way to know when
// active IME is changed without active language change.
NS_ENSURE_TRUE_VOID(sTsfTextStore);
sTsfTextStore->mIsIMM_IME = IsIMM_IME(::GetKeyboardLayout(0));
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: nsTextStore::ProcessMessage(aWindow=0x%p, "
"aMessage=WM_INPUTLANGCHANGE, aWParam=0x%08X, aLParam=0x%08X), "
"mIsIMM_IME=%s", aWindow, aWParam, aLParam,
GetBoolName(sTsfTextStore->mIsIMM_IME)));
break;
case WM_USER_TSF_TEXTCHANGE:
NS_ENSURE_TRUE_VOID(sTsfTextStore);
sTsfTextStore->OnTextChangeMsg();
aResult.mConsumed = true;
break;
}
}
/******************************************************************/
/* nsTextStore::Composition */
/******************************************************************/
@ -3470,7 +3655,7 @@ nsTextStore::Composition::GetLayoutChangeIntervalTime()
}
sTime = std::max(10,
Preferences::GetInt("intl.tsf.on_layout_change_interval", 100));
Preferences::GetInt(kPrefNameLayoutChangeInternal, 100));
return static_cast<uint32_t>(sTime);
}
@ -3581,24 +3766,16 @@ nsTextStore::Content::EndComposition(const PendingAction& aCompEnd)
bool
nsTextStore::CurrentKeyboardLayoutHasIME()
{
// XXX MSDN documents that ITfInputProcessorProfiles is available only on
// desktop apps. However, there is no known way to obtain
// ITfInputProcessorProfileMgr instance without ITfInputProcessorProfiles
// instance.
nsRefPtr<ITfInputProcessorProfiles> profiles;
HRESULT hr = ::CoCreateInstance(CLSID_TF_InputProcessorProfiles, nullptr,
CLSCTX_INPROC_SERVER,
IID_ITfInputProcessorProfiles,
getter_AddRefs(profiles));
if (FAILED(hr) || !profiles) {
if (!sInputProcessorProfiles) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: nsTextStore::CurrentKeyboardLayoutHasIME() FAILED to create "
"an input processor profiles instance"));
("TSF: nsTextStore::CurrentKeyboardLayoutHasIME() FAILED due to there is "
"no input processor profiles instance"));
return false;
}
nsRefPtr<ITfInputProcessorProfileMgr> profileMgr;
hr = profiles->QueryInterface(IID_ITfInputProcessorProfileMgr,
getter_AddRefs(profileMgr));
HRESULT hr =
sInputProcessorProfiles->QueryInterface(IID_ITfInputProcessorProfileMgr,
getter_AddRefs(profileMgr));
if (FAILED(hr) || !profileMgr) {
// On Windows Vista or later, ImmIsIME() API always returns true.
// If we failed to obtain the profile manager, we cannot know if current

View File

@ -14,6 +14,7 @@
#include "nsWindowBase.h"
#include "mozilla/Attributes.h"
#include "mozilla/TextRange.h"
#include "mozilla/WindowsVersion.h"
#include <msctf.h>
#include <textstor.h>
@ -37,6 +38,12 @@ class nsWindow;
class MetroWidget;
#endif
namespace mozilla {
namespace widget {
struct MSGResult;
} // namespace widget
} // namespace mozilla
// It doesn't work well when we notify TSF of text change
// during a mutation observer call because things get broken.
// So we post a message and notify TSF when we get it later.
@ -47,7 +54,8 @@ class MetroWidget;
*/
class nsTextStore MOZ_FINAL : public ITextStoreACP,
public ITfContextOwnerCompositionSink
public ITfContextOwnerCompositionSink,
public ITfInputProcessorProfileActivationSink
{
public: /*IUnknown*/
STDMETHODIMP_(ULONG) AddRef(void);
@ -92,6 +100,10 @@ public: /*ITfContextOwnerCompositionSink*/
STDMETHODIMP OnUpdateComposition(ITfCompositionView*, ITfRange*);
STDMETHODIMP OnEndComposition(ITfCompositionView*);
public: /*ITfInputProcessorProfileActivationSink*/
STDMETHODIMP OnActivated(DWORD, LANGID, REFCLSID, REFGUID, REFGUID,
HKL, DWORD);
protected:
typedef mozilla::widget::IMEState IMEState;
typedef mozilla::widget::InputContext InputContext;
@ -102,6 +114,10 @@ public:
static void Terminate(void);
static bool ProcessRawKeyMessage(const MSG& aMsg);
static void ProcessMessage(nsWindowBase* aWindow, UINT aMessage,
WPARAM& aWParam, LPARAM& aLParam,
mozilla::widget::MSGResult& aResult);
static void SetIMEOpenState(bool);
static bool GetIMEOpenState(void);
@ -127,14 +143,6 @@ public:
return sTsfTextStore->OnTextChangeInternal(aStart, aOldEnd, aNewEnd);
}
static void OnTextChangeMsg(void)
{
NS_ENSURE_TRUE_VOID(sTsfTextStore);
// Notify TSF text change
// (see comments on WM_USER_TSF_TEXTCHANGE in nsTextStore.h)
sTsfTextStore->OnTextChangeMsgInternal();
}
static nsresult OnSelectionChange(void)
{
NS_ENSURE_TRUE(sTsfTextStore, NS_ERROR_NOT_AVAILABLE);
@ -190,6 +198,17 @@ public:
return (IsComposing() && sTsfTextStore->mWidget == aWidget);
}
static bool IsIMM_IME()
{
return sTsfTextStore ? sTsfTextStore->mIsIMM_IME :
IsIMM_IME(::GetKeyboardLayout(0));
}
static bool IsIMM_IME(HKL aHKL)
{
return (::ImmGetIMEFileNameW(aHKL, nullptr, 0) > 0);
}
#ifdef DEBUG
// Returns true when keyboard layout has IME (TIP).
static bool CurrentKeyboardLayoutHasIME();
@ -227,7 +246,7 @@ protected:
TS_TEXTCHANGE* aTextChange);
void CommitCompositionInternal(bool);
nsresult OnTextChangeInternal(uint32_t, uint32_t, uint32_t);
void OnTextChangeMsgInternal(void);
void OnTextChangeMsg();
nsresult OnSelectionChangeInternal(void);
HRESULT GetDisplayAttribute(ITfProperty* aProperty,
ITfRange* aRange,
@ -258,6 +277,8 @@ protected:
nsRefPtr<ITfDocumentMgr> mDocumentMgr;
// Edit cookie associated with the current editing context
DWORD mEditCookie;
// Cookie of installing ITfInputProcessorProfileActivationSink
DWORD mIPProfileCookie;
// Editing context at the bottom of mDocumentMgr's context stack
nsRefPtr<ITfContext> mContext;
// Currently installed notification sink
@ -632,6 +653,9 @@ protected:
// mSink->OnSelectionChange().
bool mNotifySelectionChange;
// True if current IME is implemented with IMM.
bool mIsIMM_IME;
// TSF thread manager object for the current application
static ITfThreadMgr* sTsfThreadMgr;
// sMessagePump is QI'ed from sTsfThreadMgr
@ -654,6 +678,8 @@ protected:
static ITfDocumentMgr* sTsfDisabledDocumentMgr;
static ITfContext* sTsfDisabledContext;
static ITfInputProcessorProfiles* sInputProcessorProfiles;
// Message the Tablet Input Panel uses to flush text during blurring.
// See comments in Destroy
static UINT sFlushTIPInputMessage;

View File

@ -742,6 +742,11 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
return processResult;
}
nsTextStore::ProcessMessage(this, aMsg, aWParam, aLParam, msgResult);
if (msgResult.mConsumed) {
return processResult;
}
switch (aMsg) {
case WM_PAINT:
{
@ -862,9 +867,6 @@ MetroWidget::WindowProcedure(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLPara
default:
{
if (aWParam == WM_USER_TSF_TEXTCHANGE) {
nsTextStore::OnTextChangeMsg();
}
break;
}
}