import changes from `dev' branch of rmottola/Arctic-Fox:

- remove PM alertTime custom (911dd825ec)
- Bug 1208346 - Alert service Do Not Disturb backend. r=jaws (0047051b4e)
- Bug 1208346 - Fix manualDoNotDisturb build bustage on Android. r=bustage (39275a49bd)
- Add some shadow warnings back (64eb2adf55)
- some window fixes by Roy (72e6a9b98e)
- remove parameter of DoesD3D11DeviceWork (243dfb24f4)
- Bug 1197296. Check the error code of Map. r=bas (9debd274fd)
- Bug 1221348 - Part 1: Unify crash signatures. r=jrmuizel (80763d326d)
- Bug 1221348 - Part 2: Fix texture sharing detection code on Intel. r=jrmuizel (fb0390850d)
- Bug 1097321 - Add layers.amd-switchable-gfx.enabled pref. r=jrmuizel (3963a35cbc)
- Bug 720589 - mMatchCounts may be accessed with a nonexisting index. r=neil (fdbdd7e228)
- Bug 1224975 - add telemetry for font loading. r=m_kato (013a6e8fc7)
- Bug 1188376: Split Hello Telemetry values from general WebRTC r=jib (3887cc3201)
- Bug 1198883 - Part 1: Improve ICE candidates telemetry probes. r=bwc (2d02a3d752)
- Bug 1198883 - Part 2: Added WebRTC ICE candidates to Telemetry. r+vladan (fa8032043f)
- Bug 1201926 - Add support for keyed histograms to Fennec's Telemetry module, r=nalexander (8b96ebf026)
- Bug 1213780 - Fix Telemetry reporting repeated hang annotations for Chrome hangs. r=aklotz (afde812b08)
- Bug 1128768: Part 4 - Update telemetry to serialize BHR hang annotations; r=gfritzsche (7c1b8f5fa5)
- Bug 1215540 - Fix Telemetry reporting repeated hang annotations for Thread hangs. r=aklotz (afed35f06f)
- Bug 896740 - Limit the number of chrome-hangs reported to Telemetry. r=vladan (a37ba72225)
- missing bits of Bug 932865 - Expose thread hang stats (c19c41ae06)
- Bug 1187138 (part 1) - Replace nsBaseHashtable::Enumerate() calls in toolkit/ with iterators. r=froydnj. (ba92a8464f)
- Bug 1121040 - Don't send RETURN keypresses to content while a satchel autocomplete entry is selected. r=Gijs,smaug (762efd7cc8)
- Bug 1145146 - Remove offensive comment from nsFormFillController r=mak (7a6b0eb4e1)
- Bug 1136085 - Part 1 - Don't store & collect subsession histograms on mobile. r=vladan (911084001c)
- missing bits of  Bug 1023461 - Add HangStack class to support internal string buffer; r=vladan (599bee2150)
- Bug 1196381 - Eliminate breakpad dependency in ThreadStackHelper; r=nfroyd r=snorp (ff8a632975)
- fix misspatch of 1157282 and 1198883 (9a216ab188)
- Bug 1034138 - a. Get native stack for permahangs in BHM; r=snorp (772970d0e0)
- Bug 1211411 - Limit the number of thread hang stats reported to Telemetry. r=vladan (fd72bc8b62)
- Bug 1219751 - Change the the depth limit of the thread hangs stack to use the 99th percentile. r=gfritzsche (fc59bd7598)
- Bug 1133521 - Enable BHR on Beta. r=vladan (2501c6a0ff)
- Bug 1219216 - Fix a wrong comment in BackgroundHangMonitor.h. r=gfritzsche (e974320361)
- bits of  Bug 1134279 - Change Telemetry data producers to use the correct (d00e84b7f3)
- bits of Bug 977026 - Part 2: B2G loader (bf1208a73a)
- bug 1198450 - Firefox fails to load about:home if Firefox was installed to a folder with non-Latin name r=jimm (c4df06a69e)
- Bug 1222167 - fix initialization order in GeckoChildProcessHost; r=jld (6bad274479)
- Bug 1141693 - Build and use a PIE plugin-container on Android 5.0+. Based on a patch by Mike Hommey. r=me,glandium (78dc877aec)
- Bug 1187533 - Change how Gtk+2 plugin-container is started on Gtk+3 builds. r=billm (93c2b8a1b0)
- Bug 1063359 - Unconditionally use -Wl,--no-as-needed when building with GNU ld/gold. r=mshal (643e92ca49)
- Bug 971811 - Don't prepend an empty existing DYLD_INSERT_LIBRARIES path when launching the plugin. r=smichaud (c72df0073c)
- Bug 1189352: Fix NSPR_LOG_FILE with absolute paths for sandboxed child on Windows. r=bbondy (f4bb51c123)
- Bug 1189967 - Be slightly more explicit about some conversions to std::wstring. r=nfroyd (7bec611359)
- Bug 1201438: Add non-sandboxed Windows content processes as target peers for handle duplication. r=bbondy (1ca7f499e9)
- Bug 1201438 - Fixup for builds with disabled sandbox. (de125d156e)
- Bug 1165895: Add NPAPI sandbox rule for the crash server pipe and x64 Temp dir write access. r=bbondy (e9f601912d)
- Bug 1202988 - Don't use GetTempPath for flash's mms.cfg hack for low integrity. r=aklotz (b4a0d7f856)
- Bug 1225023: Allow Flash Player to create Adobe\Flash Player and Macromedia\Flash Player directories. r=bbondy (c5120afc1d)
- Bug 1218681 - add plugin-container standalone process code. The Code associate with ARCH. r=hev (03dfb21776)
- bug 1130976 - Flash context menu causes CPOW deadlock with AdBlock Plus, plugins should spin even loop in content process instead of the chrome process r=billm (52f4d33633)
- Bug 1157237: Move invocation of async NPP_New to an async task; r=jimm (7b6c1a577e)
- Bug 1175147 - Don't do threadsafety asserts for NPN_MemAlloc and friends, r=jimm (b4ce5b33ce)
- fix strange misspatch (8a96a61819)
- Bug 1219244 - use UniquePtr instead of nsAutoArrayPtr in dom/plugins/; r=aklotz (19fabc55b5)
- Bug 1155503: BrowserStreamParent should null out its NPStream pointer and we should check for it; r=jimm (eddb82b8b4)
- some crashrep stuff (bb2b046090)
- Bug 1192077 - Convert AndroidBridge JNIEnv calls; r=esawin (821453089e)
- Bug 554171 - Add plugin thread checks to functions that must only be called on the main thread. r=jimm (f2eb3822da)
- Bug 1149358: Ensure that plugin streams are not manipulated by PluginAsyncSurrogate if plugin destruction is imminent; r=jimm (6dd99c94ee)
- Bug 1198302 - Ensure that PluginAsyncSurrogate::NotifyAsyncInitFailed properly aborts any PluginAsyncSurrogate::WaitForInit calls. r=jimm (23c1fbfcfe)
- Bug 1201239 - Add a proper null check in PluginAsyncSurrogate::NotifyAsyncInitFailed; r=jimm (5d8ff9f8aa)
- Bug 1208059: Make nsNPAPIPluginInstance support WeakPtr and modify PluginAsyncSurrogate to use it; r=jimm (174a3166b1)
- Bug 1171453: Make ParentNPObjects aware of AsyncNPObject wrappers; r=jimm (92e608831d)
- Bug 1217726 - Fix -Wimplicit-fallthrough warnings in dom/plugins. r=jimm (32db26ede8)
- Bug 1167720 - Fix invalid window ID provided to GTK3 plugin container children. r=karlt (d8c2de0c19)
- Remove Windows-specific synchronous plugin drawing code. (bug 1218688 part 1, r=jimm) (5e4b60ea33)
- Remove Linux-specific synchronous plugin drawing code. (bug 1218688 part 2, r=jimm) (edb29f27b8)
- Remove Mac-specific synchronous plugin drawing code. (bug 1218688 part 3, r=benwa) (acc6b57b23)
- Assert that we do not attempt synchronous painting of windowless Desktop plugins. (bug 1218688 part 4, r=bsmedberg) (c34094b038)
- Bug 1195472 - Call Show after Enable on puppet widgets to avoid an assertion when running crash tests. r=aklotz (405ed2c1d1)
- Add explicit keyword to AsyncScrollBase constructor to fix static analysis build (bug 1139220 part 6, r=shu) (4cc37b9a3b)
- Bug 1146561 - Add back the visibility check for Mac plugins. r=jmuizelaar (91a4a5a8e9)
- namespace (9b4919f8fa)
- Bug 1217307 - Remove some unnecessary null checks in rest of dom/. r=njn (de5d69880a)
- Bug 1225137 - Avoid crash on some platforms if scrollbar fading is enabled and the duration is set to zero. r=spohl (a16954de2f)
- Bug 1114554 - Disable NotificationStorage debug logging. r=dholbert (c2722fa4ed)
- Bug 1073551 - fix doorhangers to not steal focus unless explicitly opened using mouse or keyboard, r=jaws (be6109cf6d)
- Bug 1169629: Add-on install confirmation notification appears anchored to older dismissed anchors. r=dao (684535c7cc)
- Bug 1194706: make sure that the notification icons and doorhangers are shown in undocked chat windows too. r=Mossop (68e0ced913)
- Bug 1207089 - Telemetry for permission notifications. r=MattN,vladan (ff421236ea)
- Bug 1215526 - part 4 - make preprocess-tab-svgs.py report extra dependencies; r=glandium (98b64b5c45)
This commit is contained in:
2023-02-24 08:22:17 +08:00
parent e4c23c8471
commit 4e6138a54f
134 changed files with 3220 additions and 1793 deletions
+1 -1
View File
@@ -130,7 +130,7 @@
#endif
#ifdef MOZ_GTK3
@BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@mozgtk2@DLL_SUFFIX@
@BINPATH@/gtk2/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
#endif
[browser]
+1 -1
View File
@@ -141,7 +141,7 @@
#endif
#ifdef MOZ_GTK3
@BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@mozgtk2@DLL_SUFFIX@
@BINPATH@/gtk2/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
#endif
[browser]
@@ -102,16 +102,16 @@
}
.notification-anchor-icon {
%ifdef MOZ_WIDGET_GTK
list-style-image: url(moz-icon://stock/gtk-dialog-info?size=16);
%else
list-style-image: url(chrome://global/skin/icons/information-16.png);
%endif
width: 16px;
height: 16px;
margin: 0 2px;
}
.default-notification-icon,
#default-notification-icon {
list-style-image: url(chrome://global/skin/icons/information-16.png);
}
.identity-notification-icon,
#identity-notification-icon {
list-style-image: url(chrome://mozapps/skin/profile/profileicon.png);
@@ -280,19 +280,22 @@
100% { transform: translateX(0); }
}
%ifdef XP_MACOSX
/* HiDPI notification icons */
@media (min-resolution: 2dppx) {
@media (min-resolution: 1.1dppx) {
#notification-popup-box {
border-image: url("chrome://browser/skin/urlbar-arrow@2x.png") 0 16 0 0 fill;
}
.default-notification-icon,
#default-notification-icon {
.notification-anchor-icon {
%ifdef MOZ_WIDGET_GTK
list-style-image: url(moz-icon://stock/gtk-dialog-info?size=dialog);
%else
list-style-image: url(chrome://global/skin/icons/information-32.png);
%endif
}
%ifdef XP_MACOSX
/* OSX only until we have icons for Windows and Linux */
.geo-notification-icon,
#geo-notification-icon {
list-style-image: url(chrome://browser/skin/Geolocation-16@2x.png);
@@ -311,6 +314,7 @@
list-style-image: url(chrome://mozapps/skin/extensions/extensionGeneric.png);
}
#login-fill-notification-icon,
#password-notification-icon {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-16@2x.png);
}
@@ -451,5 +455,5 @@
#servicesInstall-notification-icon {
list-style-image: url(chrome://browser/skin/social/services-16@2x.png);
}
}
%endif
}
+3 -1
View File
@@ -8338,7 +8338,9 @@ else
# so if the file is named libsomething.so. The lib/ path is also required
# because the unpacked file will be under the lib/ subdirectory and will
# need to be executed from that path.
MOZ_CHILD_PROCESS_NAME="lib/libplugin-container.so"
MOZ_CHILD_PROCESS_NAME="libplugin-container.so"
MOZ_CHILD_PROCESS_NAME_PIE="libplugin-container-pie.so"
AC_SUBST(MOZ_CHILD_PROCESS_NAME_PIE)
fi
MOZ_CHILD_PROCESS_BUNDLE="plugin-container.app/Contents/MacOS/"
-1
View File
@@ -848,7 +848,6 @@ GetSubmissionFromForm(nsGenericHTMLElement* aForm,
*aFormSubmission = new nsFSURLEncoded(charset, method, doc,
aOriginatingElement);
}
NS_ENSURE_TRUE(*aFormSubmission, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;
}
-5
View File
@@ -298,8 +298,6 @@ nsJSONWriter::Write(const char16_t *aBuffer, uint32_t aLength)
if (!mDidWrite) {
mBuffer = new char16_t[JSON_STREAM_BUFSIZE];
if (!mBuffer)
return NS_ERROR_OUT_OF_MEMORY;
mDidWrite = true;
}
@@ -481,9 +479,6 @@ nsresult
NS_NewJSON(nsISupports* aOuter, REFNSIID aIID, void** aResult)
{
nsJSON* json = new nsJSON();
if (!json)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(json);
*aResult = json;
-4
View File
@@ -410,8 +410,6 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
// Create the nsIStreamIO layer used by the nsIStreamIOChannel.
mIOThunk = new nsJSThunk();
if (!mIOThunk)
return NS_ERROR_OUT_OF_MEMORY;
// Create a stock input stream channel...
// Remember, until AsyncOpen is called, the script will not be evaluated
@@ -1129,8 +1127,6 @@ nsJSProtocolHandler::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
return NS_ERROR_NO_AGGREGATION;
nsJSProtocolHandler* ph = new nsJSProtocolHandler();
if (!ph)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(ph);
nsresult rv = ph->Init();
if (NS_SUCCEEDED(rv)) {
-3
View File
@@ -640,9 +640,6 @@ InitMediaCache()
return;
gMediaCache = new MediaCache();
if (!gMediaCache)
return;
nsresult rv = gMediaCache->Init();
if (NS_FAILED(rv)) {
delete gMediaCache;
-2
View File
@@ -548,8 +548,6 @@ nsresult ChannelMediaResource::OpenChannel(nsIStreamListener** aStreamListener)
}
mListener = new Listener(this);
NS_ENSURE_TRUE(mListener, NS_ERROR_OUT_OF_MEMORY);
if (aStreamListener) {
*aStreamListener = mListener;
NS_ADDREF(*aStreamListener);
+6 -3
View File
@@ -120,7 +120,9 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
#ifdef MOZ_WIDGET_ANDROID
// get the JVM
JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
JavaVM* jvm;
JNIEnv* const env = jni::GetEnvForThread();
MOZ_ALWAYS_TRUE(!env->GetJavaVM(&jvm));
if (webrtc::VideoEngine::SetAndroidObjects(jvm) != 0) {
LOG(("VieCapture:SetAndroidObjects Failed"));
@@ -245,8 +247,9 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource,
jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
// get the JVM
JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
JNIEnv *env = GetJNIForThread();
JavaVM* jvm;
JNIEnv* const env = jni::GetEnvForThread();
MOZ_ALWAYS_TRUE(!env->GetJavaVM(&jvm));
if (webrtc::VoiceEngine::SetAndroidObjects(jvm, env, (void*)context) != 0) {
LOG(("VoiceEngine:SetAndroidObjects Failed"));
+1 -1
View File
@@ -39,7 +39,7 @@ const kMessages = [
"Notification:GetAllCrossOrigin"
];
let NotificationDB = {
var NotificationDB = {
// Ensure we won't call init() while xpcom-shutdown is performed
_shutdownInProgress: false,
+1 -1
View File
@@ -4,7 +4,7 @@
"use strict";
const DEBUG = true;
const DEBUG = false;
function debug(s) { dump("-*- NotificationStorage.js: " + s + "\n"); }
const Cc = Components.classes;
+1 -1
View File
@@ -37,7 +37,7 @@ nsresult
PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
NPPluginFuncs* pFuncs, NPError* error)
{
JNIEnv* env = GetJNIForThread();
JNIEnv* env = jni::GetEnvForThread();
mozilla::AutoLocalJNIFrame jniFrame(env);
+5 -5
View File
@@ -124,7 +124,7 @@ AudioRunnable::Run()
{
PR_SetCurrentThreadName("Android Audio");
JNIEnv* jenv = GetJNIForThread();
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
mozilla::AutoLocalJNIFrame autoFrame(jenv, 2);
@@ -207,7 +207,7 @@ anp_audio_newTrack(uint32_t sampleRate, // sampling rate in Hz
return nullptr;
}
JNIEnv *jenv = GetJNIForThread();
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
s->at_class = init_jni_bindings(jenv);
s->rate = sampleRate;
@@ -303,7 +303,7 @@ anp_audio_start(ANPAudioTrack* s)
return;
}
JNIEnv *jenv = GetJNIForThread();
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
jenv->CallVoidMethod(s->output_unit, at.play);
@@ -331,7 +331,7 @@ anp_audio_pause(ANPAudioTrack* s)
return;
}
JNIEnv *jenv = GetJNIForThread();
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
jenv->CallVoidMethod(s->output_unit, at.pause);
@@ -345,7 +345,7 @@ anp_audio_stop(ANPAudioTrack* s)
}
s->isStopped = true;
JNIEnv *jenv = GetJNIForThread();
JNIEnv* const jenv = mozilla::jni::GetEnvForThread();
mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
jenv->CallVoidMethod(s->output_unit, at.stop);
+46 -11
View File
@@ -833,7 +833,6 @@ AsyncCallbackAutoLock::~AsyncCallbackAutoLock()
}
}
NPP NPPStack::sCurrentNPP = nullptr;
const char *
@@ -884,7 +883,6 @@ _geturl(NPP npp, const char* relativeURL, const char* target)
(strncmp(relativeURL, "ftp:", 4) != 0)) {
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
const char *name = nullptr;
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
host->GetPluginName(inst, &name);
@@ -1037,7 +1035,7 @@ NPError
_destroystream(NPP npp, NPStream *pstream, NPError reason)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_write called from the wrong thread\n"));
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_destroystream called from the wrong thread\n"));
return NPERR_INVALID_PARAM;
}
NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
@@ -1946,7 +1944,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
return NPERR_GENERIC_ERROR;
#endif
#if defined(XP_WIN) || (MOZ_WIDGET_GTK == 2) || defined(MOZ_WIDGET_QT)
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
case NPNVnetscapeWindow: {
if (!npp || !npp->ndata)
return NPERR_INVALID_INSTANCE_ERROR;
@@ -2105,9 +2103,7 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
return NPERR_NO_ERROR;
}
}
else {
return NPERR_GENERIC_ERROR;
}
return NPERR_GENERIC_ERROR;
}
#ifndef NP_NO_QUICKDRAW
@@ -2336,14 +2332,13 @@ _getvalue(NPP npp, NPNVariable variable, void *result)
// we no longer hand out any XPCOM objects
case NPNVDOMElement:
// fall through
case NPNVDOMWindow:
// fall through
case NPNVserviceManager:
// old XPCOM objects, no longer supported, but null out the out
// param to avoid crashing plugins that still try to use this.
*(nsISupports**)result = nullptr;
// fall through
MOZ_FALLTHROUGH;
default:
NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("NPN_getvalue unhandled get value: %d\n", variable));
return NPERR_GENERIC_ERROR;
@@ -2631,6 +2626,11 @@ NPError
_getvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
char **value, uint32_t *len)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getvalueforurl called from the wrong thread\n"));
return NPERR_GENERIC_ERROR;
}
if (!instance) {
return NPERR_INVALID_PARAM;
}
@@ -2689,6 +2689,11 @@ NPError
_setvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
const char *value, uint32_t len)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_setvalueforurl called from the wrong thread\n"));
return NPERR_GENERIC_ERROR;
}
if (!instance) {
return NPERR_INVALID_PARAM;
}
@@ -2700,7 +2705,7 @@ _setvalueforurl(NPP instance, NPNURLVariable variable, const char *url,
switch (variable) {
case NPNURLVCookie:
{
if (!url || !value || (0 >= len))
if (!value || 0 == len)
return NPERR_INVALID_PARAM;
nsresult rv = NS_ERROR_FAILURE;
@@ -2745,6 +2750,11 @@ _getauthenticationinfo(NPP instance, const char *protocol, const char *host,
char **username, uint32_t *ulen, char **password,
uint32_t *plen)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_getauthenticationinfo called from the wrong thread\n"));
return NPERR_GENERIC_ERROR;
}
if (!instance || !protocol || !host || !scheme || !realm || !username ||
!ulen || !password || !plen)
return NPERR_INVALID_PARAM;
@@ -2801,6 +2811,11 @@ _getauthenticationinfo(NPP instance, const char *protocol, const char *host,
uint32_t
_scheduletimer(NPP instance, uint32_t interval, NPBool repeat, PluginTimerFunc timerFunc)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_scheduletimer called from the wrong thread\n"));
return 0;
}
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
if (!inst)
return 0;
@@ -2811,6 +2826,11 @@ _scheduletimer(NPP instance, uint32_t interval, NPBool repeat, PluginTimerFunc t
void
_unscheduletimer(NPP instance, uint32_t timerID)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_unscheduletimer called from the wrong thread\n"));
return;
}
#ifdef MOZ_WIDGET_ANDROID
// Sometimes Flash calls this with a dead NPP instance. Ensure the one we have
// here is valid and maps to a nsNPAPIPluginInstance.
@@ -2827,6 +2847,11 @@ _unscheduletimer(NPP instance, uint32_t timerID)
NPError
_popupcontextmenu(NPP instance, NPMenu* menu)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_popupcontextmenu called from the wrong thread\n"));
return 0;
}
#ifdef MOZ_WIDGET_COCOA
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
@@ -2876,6 +2901,11 @@ _popupcontextmenu(NPP instance, NPMenu* menu)
NPBool
_convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_convertpoint called from the wrong thread\n"));
return 0;
}
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
if (!inst)
return false;
@@ -2886,6 +2916,11 @@ _convertpoint(NPP instance, double sourceX, double sourceY, NPCoordinateSpace so
void
_urlredirectresponse(NPP instance, void* notifyData, NPBool allow)
{
if (!NS_IsMainThread()) {
NPN_PLUGIN_LOG(PLUGIN_LOG_ALWAYS,("NPN_convertpoint called from the wrong thread\n"));
return;
}
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
if (!inst) {
return;
@@ -582,9 +582,6 @@ nsNPAPIPluginInstance::NewStreamFromPlugin(const char* type, const char* target,
nsIOutputStream* *result)
{
nsPluginStreamToFile* stream = new nsPluginStreamToFile(target, mOwner);
if (!stream)
return NS_ERROR_OUT_OF_MEMORY;
return stream->QueryInterface(kIOutputStreamIID, (void**)result);
}
+3
View File
@@ -32,6 +32,7 @@ class SharedPluginTexture;
#include "mozilla/TimeStamp.h"
#include "mozilla/PluginLibrary.h"
#include "mozilla/RefPtr.h"
#include "mozilla/WeakPtr.h"
class nsPluginStreamListenerPeer; // browser-initiated stream class
class nsNPAPIPluginStreamListener; // plugin-initiated stream class
@@ -77,11 +78,13 @@ public:
};
class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback
, public mozilla::SupportsWeakPtr<nsNPAPIPluginInstance>
{
private:
typedef mozilla::PluginLibrary PluginLibrary;
public:
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsNPAPIPluginInstance)
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
-5
View File
@@ -2158,9 +2158,6 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
pluginTag = new nsPluginTag(&info, fileModTime, fromExtension);
pluginFile.FreePluginInfo(info);
if (!pluginTag)
return NS_ERROR_OUT_OF_MEMORY;
pluginTag->mLibrary = library;
uint32_t state;
rv = pluginTag->GetBlocklistState(&state);
@@ -3251,8 +3248,6 @@ nsPluginHost::EnsurePrivateDirServiceProvider()
if (!mPrivateDirServiceProvider) {
nsresult rv;
mPrivateDirServiceProvider = new nsPluginDirServiceProvider();
if (!mPrivateDirServiceProvider)
return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIDirectoryService> dirService(do_GetService(kDirectoryServiceContractID, &rv));
if (NS_FAILED(rv))
return rv;
+4 -116
View File
@@ -328,13 +328,10 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
mPluginFrame = nullptr;
mWidgetCreationComplete = false;
#ifdef XP_MACOSX
memset(&mCGPluginPortCopy, 0, sizeof(NP_CGContext));
mInCGPaintLevel = 0;
mSentInitialTopLevelWindowEvent = false;
mLastWindowIsActive = false;
mLastContentFocused = false;
mLastScaleFactor = 1.0;
mColorProfile = nullptr;
mShouldBlurOnActivate = false;
#endif
mContentFocused = false;
@@ -1133,9 +1130,6 @@ void nsPluginInstanceOwner::AddToCARefreshTimer() {
if (!sCARefreshListeners) {
sCARefreshListeners = new nsTArray<nsPluginInstanceOwner*>();
if (!sCARefreshListeners) {
return;
}
}
if (sCARefreshListeners->Contains(this)) {
@@ -1146,9 +1140,6 @@ void nsPluginInstanceOwner::AddToCARefreshTimer() {
if (!sCATimer) {
sCATimer = new nsCOMPtr<nsITimer>();
if (!sCATimer) {
return;
}
}
if (sCARefreshListeners->Length() == 1) {
@@ -1176,91 +1167,6 @@ void nsPluginInstanceOwner::RemoveFromCARefreshTimer() {
}
}
void nsPluginInstanceOwner::RenderCoreAnimation(CGContextRef aCGContext,
int aWidth, int aHeight)
{
if (aWidth == 0 || aHeight == 0)
return;
if (!mCARenderer) {
mCARenderer = new nsCARenderer();
}
// aWidth and aHeight are in "display pixels". In non-HiDPI modes
// "display pixels" are device pixels. But in HiDPI modes each
// display pixel corresponds to more than one device pixel.
double scaleFactor = 1.0;
GetContentsScaleFactor(&scaleFactor);
if (!mIOSurface ||
(mIOSurface->GetWidth() != (size_t)aWidth ||
mIOSurface->GetHeight() != (size_t)aHeight ||
mIOSurface->GetContentsScaleFactor() != scaleFactor)) {
mIOSurface = nullptr;
// If the renderer is backed by an IOSurface, resize it as required.
mIOSurface = MacIOSurface::CreateIOSurface(aWidth, aHeight, scaleFactor);
if (mIOSurface) {
RefPtr<MacIOSurface> attachSurface = MacIOSurface::LookupSurface(
mIOSurface->GetIOSurfaceID(),
scaleFactor);
if (attachSurface) {
mCARenderer->AttachIOSurface(attachSurface);
} else {
NS_ERROR("IOSurface attachment failed");
mIOSurface = nullptr;
}
}
}
if (!mColorProfile) {
mColorProfile = CreateSystemColorSpace();
}
if (mCARenderer->isInit() == false) {
void *caLayer = nullptr;
nsresult rv = mInstance->GetValueFromPlugin(NPPVpluginCoreAnimationLayer, &caLayer);
if (NS_FAILED(rv) || !caLayer) {
return;
}
// We don't run Flash in-process so we can unconditionally disallow
// the offliner renderer.
mCARenderer->SetupRenderer(caLayer, aWidth, aHeight, scaleFactor,
DISALLOW_OFFLINE_RENDERER);
// Setting up the CALayer requires resetting the painting otherwise we
// get garbage for the first few frames.
FixUpPluginWindow(ePluginPaintDisable);
FixUpPluginWindow(ePluginPaintEnable);
}
CGImageRef caImage = nullptr;
nsresult rt = mCARenderer->Render(aWidth, aHeight, scaleFactor, &caImage);
if (rt == NS_OK && mIOSurface && mColorProfile) {
nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, mColorProfile,
0, 0, aWidth, aHeight);
} else if (rt == NS_OK && caImage != nullptr) {
// Significant speed up by resetting the scaling
::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone );
::CGContextTranslateCTM(aCGContext, 0, (double) aHeight * scaleFactor);
::CGContextScaleCTM(aCGContext, scaleFactor, -scaleFactor);
::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage);
} else {
NS_NOTREACHED("nsCARenderer::Render failure");
}
}
void* nsPluginInstanceOwner::GetPluginPortCopy()
{
if (GetDrawingModel() == NPDrawingModelCoreGraphics ||
GetDrawingModel() == NPDrawingModelCoreAnimation ||
GetDrawingModel() == NPDrawingModelInvalidatingCoreAnimation)
return &mCGPluginPortCopy;
return nullptr;
}
void nsPluginInstanceOwner::SetPluginPort()
{
void* pluginPort = GetPluginPort();
@@ -1268,18 +1174,6 @@ void nsPluginInstanceOwner::SetPluginPort()
return;
mPluginWindow->window = pluginPort;
}
void nsPluginInstanceOwner::BeginCGPaint()
{
++mInCGPaintLevel;
}
void nsPluginInstanceOwner::EndCGPaint()
{
--mInCGPaintLevel;
NS_ASSERTION(mInCGPaintLevel >= 0, "Mismatched call to nsPluginInstanceOwner::EndCGPaint()!");
}
#endif
// static
@@ -1367,7 +1261,7 @@ bool nsPluginInstanceOwner::AddPluginView(const LayoutDeviceRect& aRect /* = Lay
if (!mJavaView)
return false;
mJavaView = (void*)AndroidBridge::GetJNIEnv()->NewGlobalRef((jobject)mJavaView);
mJavaView = (void*)jni::GetGeckoThreadEnv()->NewGlobalRef((jobject)mJavaView);
}
if (AndroidBridge::Bridge())
@@ -1386,7 +1280,7 @@ void nsPluginInstanceOwner::RemovePluginView()
widget::GeckoAppShell::RemovePluginView(
jni::Object::Ref::From(jobject(mJavaView)), mFullScreen);
AndroidBridge::GetJNIEnv()->DeleteGlobalRef((jobject)mJavaView);
jni::GetGeckoThreadEnv()->DeleteGlobalRef((jobject)mJavaView);
mJavaView = nullptr;
if (mFullScreen)
@@ -1461,7 +1355,7 @@ void nsPluginInstanceOwner::ExitFullScreen() {
}
void nsPluginInstanceOwner::ExitFullScreen(jobject view) {
JNIEnv* env = AndroidBridge::GetJNIEnv();
JNIEnv* env = jni::GetGeckoThreadEnv();
if (sFullScreenInstance && sFullScreenInstance->mInstance &&
env->IsSameObject(view, (jobject)sFullScreenInstance->mInstance->GetJavaSurface())) {
@@ -2506,8 +2400,6 @@ nsPluginInstanceOwner::Destroy()
#ifdef XP_MACOSX
RemoveFromCARefreshTimer();
if (mColorProfile)
::CGColorSpaceRelease(mColorProfile);
#endif
nsCOMPtr<nsIContent> content = do_QueryReferent(mContent);
@@ -3089,11 +2981,7 @@ void nsPluginInstanceOwner::FixUpPluginWindow(int32_t inPaintState)
return;
}
// If we've already set up a CGContext in nsPluginFrame::PaintPlugin(), we
// don't want calls to SetPluginPort() to step on our work.
if (mInCGPaintLevel < 1) {
SetPluginPort();
}
SetPluginPort();
nsIntSize widgetClip = mPluginFrame->GetWidgetlessClipRect().Size();
-15
View File
@@ -135,19 +135,9 @@ public:
// This calls into the plugin (NPP_SetWindow) and can run script.
void FixUpPluginWindow(int32_t inPaintState);
void HidePluginWindow();
// Return a pointer to the internal nsPluginPort structure that's used to
// store a copy of plugin port info and to detect when it's been changed.
void* GetPluginPortCopy();
// Set plugin port info in the plugin (in the 'window' member of the
// NPWindow structure passed to the plugin by SetWindow()).
void SetPluginPort();
// Flag when we've set up a Thebes (and CoreGraphics) context in
// nsPluginFrame::PaintPlugin(). We need to know this in
// FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
// been called from nsPluginFrame::PaintPlugin() when we're using the
// CoreGraphics drawing model).
void BeginCGPaint();
void EndCGPaint();
#else // XP_MACOSX
void UpdateWindowPositionAndClipRect(bool aSetWindow);
void UpdateWindowVisibility(bool aVisible);
@@ -292,11 +282,6 @@ private:
RefPtr<nsPluginHost> mPluginHost;
#ifdef XP_MACOSX
NP_CGContext mCGPluginPortCopy;
int32_t mInCGPaintLevel;
RefPtr<MacIOSurface> mIOSurface;
RefPtr<nsCARenderer> mCARenderer;
CGColorSpaceRef mColorProfile;
static nsCOMPtr<nsITimer> *sCATimer;
static nsTArray<nsPluginInstanceOwner*> *sCARefreshListeners;
bool mSentInitialTopLevelWindowEvent;
+1 -1
View File
@@ -41,7 +41,7 @@ nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
{
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
*aPluginNativeWindow = new nsPluginNativeWindowPLATFORM();
return *aPluginNativeWindow ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
+1 -1
View File
@@ -57,7 +57,7 @@ nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
{
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
*aPluginNativeWindow = new nsPluginNativeWindowGtk();
return *aPluginNativeWindow ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
+1 -1
View File
@@ -62,7 +62,7 @@ nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow **aPluginNativeWindow)
{
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
*aPluginNativeWindow = new nsPluginNativeWindowQt();
return *aPluginNativeWindow ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
+1 -4
View File
@@ -575,13 +575,11 @@ nsPluginNativeWindowWin::GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWPar
if (!mCachedPluginWindowEvent)
{
event = new PluginWindowEvent();
if (!event) return nullptr;
mCachedPluginWindowEvent = event;
}
else if (mCachedPluginWindowEvent->InUse())
{
event = new PluginWindowEvent();
if (!event) return nullptr;
}
else
{
@@ -739,8 +737,7 @@ nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow)
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
*aPluginNativeWindow = new nsPluginNativeWindowWin();
return *aPluginNativeWindow ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
nsresult PLUG_DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeWindow)
@@ -735,12 +735,7 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
} else {
nsWeakPtr weakpeer =
do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this));
nsPluginByteRangeStreamListener *brrListener =
new nsPluginByteRangeStreamListener(weakpeer);
if (brrListener)
converter = brrListener;
else
return NS_ERROR_OUT_OF_MEMORY;
converter = new nsPluginByteRangeStreamListener(weakpeer);
}
mPendingRequests += numRequests;
+23 -4
View File
@@ -23,8 +23,12 @@
#include "nsPluginsDirUtils.h"
#include "nsILocalFileMac.h"
#include "mozilla/UniquePtr.h"
#include "nsCocoaFeatures.h"
#if defined(MOZ_CRASHREPORTER)
#include "nsExceptionHandler.h"
#endif
#include <string.h>
#include <stdio.h>
@@ -39,7 +43,6 @@
typedef NS_NPAPIPLUGIN_CALLBACK(const char *, NP_GETMIMEDESCRIPTION) ();
typedef NS_NPAPIPLUGIN_CALLBACK(OSErr, BP_GETSUPPORTEDMIMETYPES) (BPSupportedMIMETypes *mimeInfo, UInt32 flags);
/*
** Returns a CFBundleRef if the path refers to a Mac OS X bundle directory.
** The caller is responsible for calling CFRelease() to deallocate.
@@ -235,16 +238,16 @@ static void ParsePlistPluginInfo(nsPluginInfo& info, CFBundleRef bundle)
memset(info.fMimeDescriptionArray, 0, mimeDataArraySize);
// Allocate memory for mime dictionary keys and values
nsAutoArrayPtr<CFTypeRef> keys(new CFTypeRef[mimeDictKeyCount]);
mozilla::UniquePtr<CFTypeRef[]> keys(new CFTypeRef[mimeDictKeyCount]);
if (!keys)
return;
nsAutoArrayPtr<CFTypeRef> values(new CFTypeRef[mimeDictKeyCount]);
mozilla::UniquePtr<CFTypeRef[]> values(new CFTypeRef[mimeDictKeyCount]);
if (!values)
return;
info.fVariantCount = 0;
::CFDictionaryGetKeysAndValues(mimeDict, keys, values);
::CFDictionaryGetKeysAndValues(mimeDict, keys.get(), values.get());
for (int i = 0; i < mimeDictKeyCount; i++) {
CFTypeRef mimeString = keys[i];
if (!mimeString || ::CFGetTypeID(mimeString) != ::CFStringGetTypeID()) {
@@ -484,6 +487,14 @@ nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary)
NS_WARNING(msg.get());
return NS_ERROR_FAILURE;
}
#if defined(MOZ_CRASHREPORTER)
// The block above assumes that "fbplugin" is the filename of the plugin
// to be blocked, or that the filename starts with "fbplugin_". But we
// don't yet know for sure if this is always true. So for the time being
// record extra information in our crash logs.
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Bug_1086977"),
fileName);
#endif
}
// It's possible that our plugin has 2 entry points that'll give us mime type
@@ -493,6 +504,14 @@ nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary)
// Sadly we have to load the library for this to work.
rv = LoadPlugin(outLibrary);
#if defined(MOZ_CRASHREPORTER)
if (nsCocoaFeatures::OnYosemiteOrLater()) {
// If we didn't crash in LoadPlugin(), change the previous annotation so we
// don't sow confusion.
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Bug_1086977"),
NS_LITERAL_CSTRING("Didn't crash, please ignore"));
}
#endif
if (NS_FAILED(rv))
return rv;
+6 -5
View File
@@ -9,6 +9,7 @@
#include "PluginInstanceParent.h"
#include "nsNPAPIPlugin.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/unused.h"
// How much data are we willing to send across the wire
@@ -35,6 +36,7 @@ BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp,
BrowserStreamParent::~BrowserStreamParent()
{
mStream->pdata = nullptr;
}
void
@@ -51,7 +53,6 @@ BrowserStreamParent::RecvAsyncNPP_NewStreamResult(const NPError& rv,
PluginAsyncSurrogate* surrogate = mNPP->GetAsyncSurrogate();
MOZ_ASSERT(surrogate);
surrogate->AsyncCallArriving();
RefPtr<nsNPAPIPluginStreamListener> streamListener = mStreamListener.forget();
if (mState == DEFERRING_DESTROY) {
// We've been asked to destroy ourselves before init was complete.
mState = DYING;
@@ -61,10 +62,10 @@ BrowserStreamParent::RecvAsyncNPP_NewStreamResult(const NPError& rv,
NPError error = rv;
if (error == NPERR_NO_ERROR) {
if (!streamListener) {
if (!mStreamListener) {
return false;
}
if (streamListener->SetStreamType(stype)) {
if (mStreamListener->SetStreamType(stype)) {
mState = ALIVE;
} else {
error = NPERR_GENERIC_ERROR;
@@ -109,7 +110,7 @@ BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
if (ranges.Length() > INT32_MAX)
return false;
nsAutoArrayPtr<NPByteRange> rp(new NPByteRange[ranges.Length()]);
UniquePtr<NPByteRange[]> rp(new NPByteRange[ranges.Length()]);
for (uint32_t i = 0; i < ranges.Length(); ++i) {
rp[i].offset = ranges[i].offset;
rp[i].length = ranges[i].length;
@@ -117,7 +118,7 @@ BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges,
}
rp[ranges.Length() - 1].next = nullptr;
*result = mNPP->mNPNIface->requestread(mStream, rp);
*result = mNPP->mNPNIface->requestread(mStream, rp.get());
return true;
}
+73 -37
View File
@@ -36,6 +36,7 @@ AsyncNPObject::AsyncNPObject(PluginAsyncSurrogate* aSurrogate)
AsyncNPObject::~AsyncNPObject()
{
if (mRealObject) {
--mRealObject->asyncWrapperCount;
parent::_releaseobject(mRealObject);
mRealObject = nullptr;
}
@@ -51,11 +52,19 @@ AsyncNPObject::GetRealObject()
if (!instance) {
return nullptr;
}
NPObject* realObject = nullptr;
NPError err = instance->NPP_GetValue(NPPVpluginScriptableNPObject,
&mRealObject);
&realObject);
if (err != NPERR_NO_ERROR) {
return nullptr;
}
if (realObject->_class != PluginScriptableObjectParent::GetClass()) {
NS_ERROR("Don't know what kind of object this is!");
parent::_releaseobject(realObject);
return nullptr;
}
mRealObject = static_cast<ParentNPObject*>(realObject);
++mRealObject->asyncWrapperCount;
return mRealObject;
}
@@ -92,7 +101,6 @@ bool RecursionGuard::sHasEntered = false;
PluginAsyncSurrogate::PluginAsyncSurrogate(PluginModuleParent* aParent)
: mParent(aParent)
, mInstance(nullptr)
, mMode(0)
, mWindow(nullptr)
, mAcceptCalls(false)
@@ -114,7 +122,10 @@ PluginAsyncSurrogate::Init(NPMIMEType aPluginType, NPP aInstance, uint16_t aMode
int16_t aArgc, char* aArgn[], char* aArgv[])
{
mMimeType = aPluginType;
mInstance = aInstance;
nsNPAPIPluginInstance* instance =
static_cast<nsNPAPIPluginInstance*>(aInstance->ndata);
MOZ_ASSERT(instance);
mInstance = instance;
mMode = aMode;
for (int i = 0; i < aArgc; ++i) {
mNames.AppendElement(NullableString(aArgn[i]));
@@ -153,7 +164,11 @@ PluginAsyncSurrogate::Cast(NPP aInstance)
nsresult
PluginAsyncSurrogate::NPP_New(NPError* aError)
{
nsresult rv = mParent->NPP_NewInternal(mMimeType.BeginWriting(), mInstance,
if (!mInstance) {
return NS_ERROR_NULL_POINTER;
}
nsresult rv = mParent->NPP_NewInternal(mMimeType.BeginWriting(), GetNPP(),
mMode, mNames, mValues, nullptr,
aError);
if (NS_FAILED(rv)) {
@@ -190,11 +205,21 @@ PluginAsyncSurrogate::NotifyDestroyPending(NPP aInstance)
surrogate->NotifyDestroyPending();
}
NPP
PluginAsyncSurrogate::GetNPP()
{
MOZ_ASSERT(mInstance);
NPP npp;
DebugOnly<nsresult> rv = mInstance->GetNPP(&npp);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return npp;
}
void
PluginAsyncSurrogate::NotifyDestroyPending()
{
mDestroyPending = true;
nsJSNPRuntime::OnPluginDestroyPending(mInstance);
nsJSNPRuntime::OnPluginDestroyPending(GetNPP());
}
NPError
@@ -204,7 +229,7 @@ PluginAsyncSurrogate::NPP_Destroy(NPSavedData** aSave)
if (!WaitForInit()) {
return NPERR_GENERIC_ERROR;
}
return PluginModuleParent::NPP_Destroy(mInstance, aSave);
return PluginModuleParent::NPP_Destroy(GetNPP(), aSave);
}
NPError
@@ -214,12 +239,13 @@ PluginAsyncSurrogate::NPP_GetValue(NPPVariable aVariable, void* aRetval)
if (!WaitForInit()) {
return NPERR_GENERIC_ERROR;
}
PluginInstanceParent* instance = PluginInstanceParent::Cast(mInstance);
PluginInstanceParent* instance = PluginInstanceParent::Cast(GetNPP());
MOZ_ASSERT(instance);
return instance->NPP_GetValue(aVariable, aRetval);
}
NPObject* npobject = parent::_createobject(mInstance,
NPObject* npobject = parent::_createobject(GetNPP(),
const_cast<NPClass*>(GetClass()));
MOZ_ASSERT(npobject);
MOZ_ASSERT(npobject->_class == GetClass());
@@ -234,7 +260,7 @@ PluginAsyncSurrogate::NPP_SetValue(NPNVariable aVariable, void* aValue)
if (!WaitForInit()) {
return NPERR_GENERIC_ERROR;
}
return PluginModuleParent::NPP_SetValue(mInstance, aVariable, aValue);
return PluginModuleParent::NPP_SetValue(GetNPP(), aVariable, aValue);
}
NPError
@@ -420,7 +446,10 @@ PluginAsyncSurrogate::DestroyAsyncStream(NPStream* aStream)
// streamListener was suspended during async init. We must resume the stream
// request prior to calling _destroystream for cleanup to work correctly.
streamListener->ResumeRequest();
parent::_destroystream(mInstance, aStream, NPRES_DONE);
if (!mInstance) {
return;
}
parent::_destroystream(GetNPP(), aStream, NPRES_DONE);
}
/* static */ bool
@@ -436,16 +465,20 @@ PluginAsyncSurrogate::SetStreamType(NPStream* aStream, uint16_t aStreamType)
void
PluginAsyncSurrogate::OnInstanceCreated(PluginInstanceParent* aInstance)
{
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
uint16_t streamType = NP_NORMAL;
NPError curError = aInstance->NPP_NewStream(
const_cast<char*>(NullableStringGet(curPendingCall.mType)),
curPendingCall.mStream, curPendingCall.mSeekable,
&streamType);
if (curError != NPERR_NO_ERROR) {
// If we failed here then the send failed and we need to clean up
DestroyAsyncStream(curPendingCall.mStream);
if (!mDestroyPending) {
// If NPP_Destroy has already been called then these streams have already
// been cleaned up on the browser side and are no longer valid.
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
uint16_t streamType = NP_NORMAL;
NPError curError = aInstance->NPP_NewStream(
const_cast<char*>(NullableStringGet(curPendingCall.mType)),
curPendingCall.mStream, curPendingCall.mSeekable,
&streamType);
if (curError != NPERR_NO_ERROR) {
// If we failed here then the send failed and we need to clean up
DestroyAsyncStream(curPendingCall.mStream);
}
}
}
mPendingNewStreamCalls.Clear();
@@ -543,23 +576,26 @@ PluginAsyncSurrogate::AsyncCallArriving()
void
PluginAsyncSurrogate::NotifyAsyncInitFailed()
{
// Clean up any pending NewStream requests
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
DestroyAsyncStream(curPendingCall.mStream);
if (!mDestroyPending) {
// Clean up any pending NewStream requests
for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) {
PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i];
DestroyAsyncStream(curPendingCall.mStream);
}
}
mPendingNewStreamCalls.Clear();
nsNPAPIPluginInstance* inst =
static_cast<nsNPAPIPluginInstance*>(mInstance->ndata);
if (!inst) {
// Make sure that any WaitForInit calls on this surrogate will fail, or else
// we'll be perma-blocked
mInitCancelled = true;
if (!mInstance) {
return;
}
nsPluginInstanceOwner* owner = inst->GetOwner();
if (!owner) {
return;
nsPluginInstanceOwner* owner = mInstance->GetOwner();
if (owner) {
owner->NotifyHostAsyncInitFailed();
}
owner->NotifyHostAsyncInitFailed();
}
// static
@@ -645,11 +681,11 @@ PluginAsyncSurrogate::ScriptableHasMethod(NPObject* aObject,
// initialization, we should try again.
const NPNetscapeFuncs* npn = object->mSurrogate->mParent->GetNetscapeFuncs();
NPObject* pluginObject = nullptr;
NPError nperror = npn->getvalue(object->mSurrogate->mInstance,
NPError nperror = npn->getvalue(object->mSurrogate->GetNPP(),
NPNVPluginElementNPObject,
(void*)&pluginObject);
if (nperror == NPERR_NO_ERROR) {
NPPAutoPusher nppPusher(object->mSurrogate->mInstance);
NPPAutoPusher nppPusher(object->mSurrogate->GetNPP());
result = pluginObject->_class->hasMethod(pluginObject, aName);
npn->releaseobject(pluginObject);
NPUTF8* idstr = npn->utf8fromidentifier(aName);
@@ -698,10 +734,10 @@ PluginAsyncSurrogate::GetPropertyHelper(NPObject* aObject, NPIdentifier aName,
if (!success) {
const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs();
NPObject* pluginObject = nullptr;
NPError nperror = npn->getvalue(mInstance, NPNVPluginElementNPObject,
NPError nperror = npn->getvalue(GetNPP(), NPNVPluginElementNPObject,
(void*)&pluginObject);
if (nperror == NPERR_NO_ERROR) {
NPPAutoPusher nppPusher(mInstance);
NPPAutoPusher nppPusher(GetNPP());
bool hasProperty = nsJSObjWrapper::HasOwnProperty(pluginObject, aName);
NPUTF8* idstr = npn->utf8fromidentifier(aName);
npn->memfree(idstr);
@@ -806,11 +842,11 @@ PluginAsyncSurrogate::ScriptableHasProperty(NPObject* aObject,
// object hadn't been set yet. Now that we're further along in
// initialization, we should try again.
NPObject* pluginObject = nullptr;
NPError nperror = npn->getvalue(object->mSurrogate->mInstance,
NPError nperror = npn->getvalue(object->mSurrogate->GetNPP(),
NPNVPluginElementNPObject,
(void*)&pluginObject);
if (nperror == NPERR_NO_ERROR) {
NPPAutoPusher nppPusher(object->mSurrogate->mInstance);
NPPAutoPusher nppPusher(object->mSurrogate->GetNPP());
result = nsJSObjWrapper::HasOwnProperty(pluginObject, aName);
npn->releaseobject(pluginObject);
idstr = npn->utf8fromidentifier(aName);
+4 -3
View File
@@ -21,6 +21,7 @@
namespace mozilla {
namespace plugins {
struct ParentNPObject;
class PluginInstanceParent;
class PluginModuleParent;
@@ -59,7 +60,7 @@ public:
virtual PluginInstanceParent*
GetInstance() { return nullptr; }
NPP GetNPP() { return mInstance; }
NPP GetNPP();
bool GetPropertyHelper(NPObject* aObject, NPIdentifier aName,
bool* aHasProperty, bool* aHasMethod,
@@ -140,7 +141,7 @@ private:
PluginModuleParent* mParent;
// These values are used to construct the plugin instance
nsCString mMimeType;
NPP mInstance;
mozilla::WeakPtr<nsNPAPIPluginInstance> mInstance;
uint16_t mMode;
InfallibleTArray<nsCString> mNames;
InfallibleTArray<nsCString> mValues;
@@ -168,7 +169,7 @@ struct AsyncNPObject : NPObject
NPObject* GetRealObject();
RefPtr<PluginAsyncSurrogate> mSurrogate;
NPObject* mRealObject;
ParentNPObject* mRealObject;
};
class MOZ_STACK_CLASS PushSurrogateAcceptCalls
+5 -216
View File
@@ -33,6 +33,7 @@ using mozilla::gfx::SharedDIBSurface;
#include "mozilla/ipc/MessageChannel.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/UniquePtr.h"
#include "ImageContainer.h"
using namespace mozilla;
@@ -188,9 +189,6 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
mWsInfo.display = DefaultXDisplay();
#endif
#endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
#if defined(OS_WIN)
memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
#endif // OS_WIN
#if defined(OS_WIN)
InitPopupMenuHook();
if (GetQuirks() & QUIRK_UNITY_FIXUP_MOUSE_CAPTURE) {
@@ -231,8 +229,8 @@ PluginInstanceChild::DoNPP_New()
NS_ASSERTION(argc == (int) mValues.Length(),
"argn.length != argv.length");
nsAutoArrayPtr<char*> argn(new char*[1 + argc]);
nsAutoArrayPtr<char*> argv(new char*[1 + argc]);
UniquePtr<char*[]> argn(new char*[1 + argc]);
UniquePtr<char*[]> argv(new char*[1 + argc]);
argn[argc] = 0;
argv[argc] = 0;
@@ -244,7 +242,7 @@ PluginInstanceChild::DoNPP_New()
NPP npp = GetNPP();
NPError rv = mPluginIface->newp((char*)NullableStringGet(mMimeType), npp,
mMode, argc, argn, argv, 0);
mMode, argc, argn.get(), argv.get(), 0);
if (NPERR_NO_ERROR != rv) {
return rv;
}
@@ -502,6 +500,7 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
case NPNVSupportsXEmbedBool:
case NPNVSupportsWindowless:
NS_NOTREACHED("NPNVariable should be handled in PluginModuleChild.");
MOZ_FALLTHROUGH;
#endif
default:
@@ -510,7 +509,6 @@ PluginInstanceChild::NPN_GetValue(NPNVariable aVar,
(int) aVar, NPNVariableToString(aVar)));
return NPERR_GENERIC_ERROR;
}
}
#ifdef MOZ_WIDGET_COCOA
@@ -821,21 +819,6 @@ PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent& event,
if (WM_NULL == evcopy.event)
return true;
// Painting for win32. SharedSurfacePaint handles everything.
if (mWindow.type == NPWindowTypeDrawable) {
if (evcopy.event == WM_PAINT) {
*handled = SharedSurfacePaint(evcopy);
return true;
}
else if (DoublePassRenderingEvent() == evcopy.event) {
// We'll render to mSharedSurfaceDib first, then render to a cached bitmap
// we store locally. The two passes are for alpha extraction, so the second
// pass must be to a flat white surface in order for things to work.
mAlphaExtract.doublePass = RENDER_BACK_ONE;
*handled = true;
return true;
}
}
*handled = WinlessHandleEvent(evcopy);
return true;
#endif
@@ -1296,13 +1279,6 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
}
break;
case NPWindowTypeDrawable:
mWindow.type = aWindow.type;
if (GetQuirks() & QUIRK_FLASH_THROTTLE_WMUSER_EVENTS)
SetupFlashMsgThrottle();
return SharedSurfaceSetWindow(aWindow);
break;
default:
NS_NOTREACHED("Bad plugin window type.");
return false;
@@ -2024,187 +2000,6 @@ PluginInstanceChild::WinlessHandleEvent(NPEvent& event)
return handled;
}
/* windowless drawing helpers */
bool
PluginInstanceChild::SharedSurfaceSetWindow(const NPRemoteWindow& aWindow)
{
// If the surfaceHandle is empty, parent is telling us we can reuse our cached
// memory surface and hdc. Otherwise, we need to reset, usually due to a
// expanding plugin port size.
if (!aWindow.surfaceHandle) {
if (!mSharedSurfaceDib.IsValid()) {
return false;
}
}
else {
// Attach to the new shared surface parent handed us.
if (NS_FAILED(mSharedSurfaceDib.Attach((SharedDIB::Handle)aWindow.surfaceHandle,
aWindow.width, aWindow.height, false)))
return false;
// Free any alpha extraction resources if needed. This will be reset
// the next time it's used.
AlphaExtractCacheRelease();
}
// NPRemoteWindow's origin is the origin of our shared dib.
mWindow.x = aWindow.x;
mWindow.y = aWindow.y;
mWindow.width = aWindow.width;
mWindow.height = aWindow.height;
mWindow.type = aWindow.type;
mWindow.window = reinterpret_cast<void*>(mSharedSurfaceDib.GetHDC());
::SetViewportOrgEx(mSharedSurfaceDib.GetHDC(),
-aWindow.x, -aWindow.y, nullptr);
if (mPluginIface->setwindow)
mPluginIface->setwindow(&mData, &mWindow);
return true;
}
void
PluginInstanceChild::SharedSurfaceRelease()
{
mSharedSurfaceDib.Close();
AlphaExtractCacheRelease();
}
/* double pass cache buffer - (rarely) used in cases where alpha extraction
* occurs for windowless plugins. */
bool
PluginInstanceChild::AlphaExtractCacheSetup()
{
AlphaExtractCacheRelease();
mAlphaExtract.hdc = ::CreateCompatibleDC(nullptr);
if (!mAlphaExtract.hdc)
return false;
BITMAPINFOHEADER bmih;
memset((void*)&bmih, 0, sizeof(BITMAPINFOHEADER));
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = mWindow.width;
bmih.biHeight = mWindow.height;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
void* ppvBits = nullptr;
mAlphaExtract.bmp = ::CreateDIBSection(mAlphaExtract.hdc,
(BITMAPINFO*)&bmih,
DIB_RGB_COLORS,
(void**)&ppvBits,
nullptr,
(unsigned long)sizeof(BITMAPINFOHEADER));
if (!mAlphaExtract.bmp)
return false;
DeleteObject(::SelectObject(mAlphaExtract.hdc, mAlphaExtract.bmp));
return true;
}
void
PluginInstanceChild::AlphaExtractCacheRelease()
{
if (mAlphaExtract.bmp)
::DeleteObject(mAlphaExtract.bmp);
if (mAlphaExtract.hdc)
::DeleteObject(mAlphaExtract.hdc);
mAlphaExtract.bmp = nullptr;
mAlphaExtract.hdc = nullptr;
}
void
PluginInstanceChild::UpdatePaintClipRect(RECT* aRect)
{
if (aRect) {
// Update the clip rect on our internal hdc
HRGN clip = ::CreateRectRgnIndirect(aRect);
::SelectClipRgn(mSharedSurfaceDib.GetHDC(), clip);
::DeleteObject(clip);
}
}
int16_t
PluginInstanceChild::SharedSurfacePaint(NPEvent& evcopy)
{
if (!mPluginIface->event)
return false;
RECT* pRect = reinterpret_cast<RECT*>(evcopy.lParam);
switch(mAlphaExtract.doublePass) {
case RENDER_NATIVE:
// pass the internal hdc to the plugin
UpdatePaintClipRect(pRect);
evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC());
return mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
break;
case RENDER_BACK_ONE:
// Handle a double pass render used in alpha extraction for transparent
// plugins. (See nsPluginFrame and gfxWindowsNativeDrawing for details.)
// We render twice, once to the shared dib, and once to a cache which
// we copy back on a second paint. These paints can't be spread across
// multiple rpc messages as delays cause animation frame changes.
if (!mAlphaExtract.bmp && !AlphaExtractCacheSetup()) {
mAlphaExtract.doublePass = RENDER_NATIVE;
return false;
}
// See gfxWindowsNativeDrawing, color order doesn't have to match.
UpdatePaintClipRect(pRect);
::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
evcopy.wParam = WPARAM(mSharedSurfaceDib.GetHDC());
if (!mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy))) {
mAlphaExtract.doublePass = RENDER_NATIVE;
return false;
}
// Copy to cache. We render to shared dib so we don't have to call
// setwindow between calls (flash issue).
::BitBlt(mAlphaExtract.hdc,
pRect->left,
pRect->top,
pRect->right - pRect->left,
pRect->bottom - pRect->top,
mSharedSurfaceDib.GetHDC(),
pRect->left,
pRect->top,
SRCCOPY);
::FillRect(mSharedSurfaceDib.GetHDC(), pRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
if (!mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy))) {
mAlphaExtract.doublePass = RENDER_NATIVE;
return false;
}
mAlphaExtract.doublePass = RENDER_BACK_TWO;
return true;
break;
case RENDER_BACK_TWO:
// copy our cached surface back
UpdatePaintClipRect(pRect);
::BitBlt(mSharedSurfaceDib.GetHDC(),
pRect->left,
pRect->top,
pRect->right - pRect->left,
pRect->bottom - pRect->top,
mAlphaExtract.hdc,
pRect->left,
pRect->top,
SRCCOPY);
mAlphaExtract.doublePass = RENDER_NATIVE;
return true;
break;
}
return false;
}
/* flash msg throttling helpers */
// Flash has the unfortunate habit of flooding dispatch loops with custom
@@ -2313,7 +2108,6 @@ PluginInstanceChild::EnumThreadWindowsCallback(HWND hWnd,
return TRUE;
}
void
PluginInstanceChild::SetupFlashMsgThrottle()
{
@@ -2367,9 +2161,6 @@ PluginInstanceChild::FlashThrottleMessage(HWND aWnd,
// that's done in Destroy.
FlashThrottleAsyncMsg* task = new FlashThrottleAsyncMsg(this,
aWnd, aMsg, aWParam, aLParam, isWindowed);
if (!task)
return;
{
MutexAutoLock lock(mAsyncCallMutex);
mPendingAsyncCalls.AppendElement(task);
@@ -2610,7 +2401,6 @@ StreamNotifyChild::ActorDestroy(ActorDestroyReason why)
}
}
void
StreamNotifyChild::SetAssociatedStream(BrowserStreamChild* bs)
{
@@ -4051,7 +3841,6 @@ PluginInstanceChild::Destroy()
mCachedElementActor = nullptr;
#if defined(OS_WIN)
SharedSurfaceRelease();
DestroyWinlessPopupSurrogate();
UnhookWinlessFlashThrottle();
DestroyPluginWindow();
-23
View File
@@ -427,29 +427,6 @@ private:
*/
nsAutoPtr< nsTHashtable<DeletingObjectEntry> > mDeletingHash;
#if defined(OS_WIN)
private:
// Shared dib rendering management for windowless plugins.
bool SharedSurfaceSetWindow(const NPRemoteWindow& aWindow);
int16_t SharedSurfacePaint(NPEvent& evcopy);
void SharedSurfaceRelease();
bool AlphaExtractCacheSetup();
void AlphaExtractCacheRelease();
void UpdatePaintClipRect(RECT* aRect);
private:
enum {
RENDER_NATIVE,
RENDER_BACK_ONE,
RENDER_BACK_TWO
};
gfx::SharedDIBWin mSharedSurfaceDib;
struct {
uint16_t doublePass;
HDC hdc;
HBITMAP bmp;
} mAlphaExtract;
#endif // defined(OS_WIN)
#if defined(MOZ_WIDGET_COCOA)
private:
#if defined(__i386__)
+16 -133
View File
@@ -196,7 +196,6 @@ PluginInstanceParent::ActorDestroy(ActorDestroyReason why)
if (why == AbnormalShutdown) {
// If the plugin process crashes, this is the only
// chance we get to destroy resources.
SharedSurfaceRelease();
UnsubclassPluginWindow();
}
#endif
@@ -224,7 +223,6 @@ PluginInstanceParent::Destroy()
}
#if defined(OS_WIN)
SharedSurfaceRelease();
UnsubclassPluginWindow();
#endif
@@ -957,11 +955,6 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
#if defined(OS_WIN)
// On windowless controls, reset the shared memory surface as needed.
if (mWindowType == NPWindowTypeDrawable) {
// SharedSurfaceSetWindow will take care of NPRemoteWindow.
if (!SharedSurfaceSetWindow(aWindow, window)) {
return NPERR_OUT_OF_MEMORY_ERROR;
}
MaybeCreateChildPopupSurrogate();
} else {
SubclassPluginWindow(reinterpret_cast<HWND>(aWindow->window));
@@ -1196,23 +1189,7 @@ PluginInstanceParent::NPP_HandleEvent(void* event)
#if defined(OS_WIN)
if (mWindowType == NPWindowTypeDrawable) {
if (DoublePassRenderingEvent() == npevent->event) {
return CallPaint(npremoteevent, &handled) && handled;
}
switch (npevent->event) {
case WM_PAINT:
{
RECT rect;
SharedSurfaceBeforePaint(rect, npremoteevent);
if (!CallPaint(npremoteevent, &handled)) {
handled = false;
}
SharedSurfaceAfterPaint(npevent);
return handled;
}
break;
case WM_KILLFOCUS:
{
// When the user selects fullscreen mode in Flash video players,
@@ -1444,6 +1421,12 @@ PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason)
FULLFUNCTION, (void*) stream, (int) reason));
AStream* s = static_cast<AStream*>(stream->pdata);
if (!s) {
// The stream has already been deleted by other means.
// With async plugin init this could happen if async NPP_NewStream
// returns an error code.
return NPERR_NO_ERROR;
}
if (s->IsBrowserStream()) {
BrowserStreamParent* sp =
static_cast<BrowserStreamParent*>(s);
@@ -1593,11 +1576,6 @@ PluginInstanceParent::GetActorForNPObject(NPObject* aObject)
}
actor = new PluginScriptableObjectParent(LocalObject);
if (!actor) {
NS_ERROR("Out of memory!");
return nullptr;
}
if (!SendPPluginScriptableObjectConstructor(actor)) {
NS_WARNING("Failed to send constructor message!");
return nullptr;
@@ -1764,10 +1742,17 @@ PluginInstanceParent::RecvAsyncNPP_NewResult(const NPError& aResult)
mSurrogate->SetAcceptingCalls(true);
}
// It is possible for a plugin instance to outlive its owner (eg. When a
// PluginDestructionGuard was on the stack at the time the owner was being
// destroyed). We need to handle that case.
nsPluginInstanceOwner* owner = GetOwner();
// It is possible for a plugin instance to outlive its owner when async
// plugin init is turned on, so we need to handle that case.
if (aResult != NPERR_NO_ERROR || !owner) {
if (!owner) {
// We can't do anything at this point, just return. Any pending browser
// streams will be cleaned up when the plugin instance is destroyed.
return true;
}
if (aResult != NPERR_NO_ERROR) {
mSurrogate->NotifyAsyncInitFailed();
return true;
}
@@ -1939,108 +1924,6 @@ PluginInstanceParent::UnsubclassPluginWindow()
* painting: mPluginPort (nsIntRect, saved in SetWindow)
*/
void
PluginInstanceParent::SharedSurfaceRelease()
{
mSharedSurfaceDib.Close();
}
bool
PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow,
NPRemoteWindow& aRemoteWindow)
{
aRemoteWindow.window = 0;
aRemoteWindow.x = aWindow->x;
aRemoteWindow.y = aWindow->y;
aRemoteWindow.width = aWindow->width;
aRemoteWindow.height = aWindow->height;
aRemoteWindow.type = aWindow->type;
nsIntRect newPort(aWindow->x, aWindow->y, aWindow->width, aWindow->height);
// save the the rect location within the browser window.
mPluginPort = newPort;
// move the port to our shared surface origin
newPort.MoveTo(0,0);
// check to see if we have the room in shared surface
if (mSharedSurfaceDib.IsValid() && mSharedSize.Contains(newPort)) {
// ok to paint
aRemoteWindow.surfaceHandle = 0;
return true;
}
// allocate a new shared surface
SharedSurfaceRelease();
if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast<HDC>(aWindow->window),
newPort.width, newPort.height, false)))
return false;
// save the new shared surface size we just allocated
mSharedSize = newPort;
base::SharedMemoryHandle handle;
if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(OtherPid(), &handle))) {
return false;
}
aRemoteWindow.surfaceHandle = handle;
return true;
}
void
PluginInstanceParent::SharedSurfaceBeforePaint(RECT& rect,
NPRemoteEvent& npremoteevent)
{
RECT* dr = (RECT*)npremoteevent.event.lParam;
HDC parentHdc = (HDC)npremoteevent.event.wParam;
nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top);
dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); // should always be smaller than dirtyRect
::BitBlt(mSharedSurfaceDib.GetHDC(),
dirtyRect.x,
dirtyRect.y,
dirtyRect.width,
dirtyRect.height,
parentHdc,
dr->left,
dr->top,
SRCCOPY);
// setup the translated dirty rect we'll send to the child
rect.left = dirtyRect.x;
rect.top = dirtyRect.y;
rect.right = dirtyRect.x + dirtyRect.width;
rect.bottom = dirtyRect.y + dirtyRect.height;
npremoteevent.event.wParam = WPARAM(0);
npremoteevent.event.lParam = LPARAM(&rect);
}
void
PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent)
{
RECT* dr = (RECT*)npevent->lParam;
HDC parentHdc = (HDC)npevent->wParam;
nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top);
dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y);
// src copy the shared dib into the parent surface we are handed.
::BitBlt(parentHdc,
dr->left,
dr->top,
dirtyRect.width,
dirtyRect.height,
mSharedSurfaceDib.GetHDC(),
dirtyRect.x,
dirtyRect.y,
SRCCOPY);
}
bool
PluginInstanceParent::MaybeCreateAndParentChildPluginWindow()
{
-6
View File
@@ -353,11 +353,6 @@ private:
#if defined(OS_WIN)
private:
// Used in rendering windowless plugins in other processes.
bool SharedSurfaceSetWindow(const NPWindow* aWindow, NPRemoteWindow& aRemoteWindow);
void SharedSurfaceBeforePaint(RECT &rect, NPRemoteEvent& npremoteevent);
void SharedSurfaceAfterPaint(NPEvent* npevent);
void SharedSurfaceRelease();
// Used in handling parent/child forwarding of events.
static LRESULT CALLBACK PluginWindowHookProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
@@ -368,7 +363,6 @@ private:
void MaybeCreateChildPopupSurrogate();
private:
gfx::SharedDIBWin mSharedSurfaceDib;
nsIntRect mPluginPort;
nsIntRect mSharedSize;
HWND mPluginHWND;
-16
View File
@@ -54,9 +54,6 @@ NPRemoteWindow::NPRemoteWindow() :
, visualID(0)
, colormap(0)
#endif /* XP_UNIX */
#if defined(XP_WIN)
,surfaceHandle(0)
#endif
#if defined(XP_MACOSX)
,contentsScaleFactor(1.0)
#endif
@@ -156,18 +153,5 @@ void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v)
VOID_TO_NPVARIANT(*v);
}
#ifdef XP_WIN
// The private event used for double-pass widgetless plugin rendering.
UINT DoublePassRenderingEvent()
{
static UINT gEventID = 0;
if (!gEventID)
gEventID = ::RegisterWindowMessage(L"MozDoublePassMsg");
return gEventID;
}
#endif
} // namespace plugins
} // namespace mozilla
+3 -22
View File
@@ -12,6 +12,7 @@
#include "mozilla/ipc/MessageChannel.h"
#include "mozilla/ipc/CrossProcessMutex.h"
#include "mozilla/UniquePtr.h"
#include "gfxipc/ShadowLayerUtils.h"
#include "npapi.h"
@@ -90,9 +91,6 @@ struct NPRemoteWindow
VisualID visualID;
Colormap colormap;
#endif /* XP_UNIX */
#if defined(XP_WIN)
base::SharedMemoryHandle surfaceHandle;
#endif
#if defined(XP_MACOSX)
double contentsScaleFactor;
#endif
@@ -251,11 +249,6 @@ struct DeletingObjectEntry : public nsPtrHashKey<NPObject>
bool mDeleted;
};
#ifdef XP_WIN
// The private event used for double-pass widgetless plugin rendering.
UINT DoublePassRenderingEvent();
#endif
} /* namespace plugins */
} /* namespace mozilla */
@@ -342,9 +335,6 @@ struct ParamTraits<mozilla::plugins::NPRemoteWindow>
aMsg->WriteULong(aParam.visualID);
aMsg->WriteULong(aParam.colormap);
#endif
#if defined(XP_WIN)
WriteParam(aMsg, aParam.surfaceHandle);
#endif
#if defined(XP_MACOSX)
aMsg->WriteDouble(aParam.contentsScaleFactor);
#endif
@@ -374,12 +364,6 @@ struct ParamTraits<mozilla::plugins::NPRemoteWindow>
return false;
#endif
#if defined(XP_WIN)
base::SharedMemoryHandle surfaceHandle;
if (!ReadParam(aMsg, aIter, &surfaceHandle))
return false;
#endif
#if defined(XP_MACOSX)
double contentsScaleFactor;
if (!aMsg->ReadDouble(aIter, &contentsScaleFactor))
@@ -397,9 +381,6 @@ struct ParamTraits<mozilla::plugins::NPRemoteWindow>
aResult->visualID = visualID;
aResult->colormap = colormap;
#endif
#if defined(XP_WIN)
aResult->surfaceHandle = surfaceHandle;
#endif
#if defined(XP_MACOSX)
aResult->contentsScaleFactor = contentsScaleFactor;
#endif
@@ -437,10 +418,10 @@ struct ParamTraits<NPString>
}
const char* messageBuffer = nullptr;
nsAutoArrayPtr<char> newBuffer(new char[byteCount]);
mozilla::UniquePtr<char[]> newBuffer(new char[byteCount]);
if (newBuffer && aMsg->ReadBytes(aIter, &messageBuffer, byteCount )) {
memcpy((void*)messageBuffer, newBuffer.get(), byteCount);
aResult->UTF8Characters = newBuffer.forget();
aResult->UTF8Characters = newBuffer.release();
return true;
}
}
+43 -16
View File
@@ -45,6 +45,8 @@
#ifdef XP_WIN
#include "nsWindowsDllInterceptor.h"
#include "mozilla/widget/AudioSession.h"
#include "WinUtils.h"
#include <knownfolders.h>
#endif
#ifdef MOZ_WIDGET_COCOA
@@ -159,7 +161,7 @@ PluginModuleChild::PluginModuleChild(bool aIsChrome)
PluginModuleChild::~PluginModuleChild()
{
if (mTransport) {
// For some reason IPDL doesn't autmatically delete the channel for a
// For some reason IPDL doesn't automatically delete the channel for a
// bridged protocol (bug 1090570). So we have to do it ourselves. This
// code is only invoked for PluginModuleChild instances created via
// bridging; otherwise mTransport is null.
@@ -302,6 +304,8 @@ PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
return false;
}
GetIPCChannel()->SetAbortOnError(true);
// TODO: use PluginPRLibrary here
#if defined(OS_LINUX) || defined(OS_BSD)
@@ -315,10 +319,6 @@ PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
NS_ASSERTION(mInitializeFunc, "couldn't find NP_Initialize()");
#elif defined(OS_WIN) || defined(OS_MACOSX)
// no, don't do that
//GetIPCChannel()->SetAbortOnError(true);
mShutdownFunc =
(NP_PLUGINSHUTDOWN)PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
@@ -1336,8 +1336,6 @@ void
_memfree(void* aPtr)
{
PLUGIN_LOG_DEBUG_FUNCTION;
// Only assert plugin thread here for consistency with in-process plugins.
AssertPluginThread();
NS_Free(aPtr);
}
@@ -1345,8 +1343,6 @@ uint32_t
_memflush(uint32_t aSize)
{
PLUGIN_LOG_DEBUG_FUNCTION;
// Only assert plugin thread here for consistency with in-process plugins.
AssertPluginThread();
return 0;
}
@@ -1405,8 +1401,6 @@ void*
_memalloc(uint32_t aSize)
{
PLUGIN_LOG_DEBUG_FUNCTION;
// Only assert plugin thread here for consistency with in-process plugins.
AssertPluginThread();
return NS_Alloc(aSize);
}
@@ -1819,7 +1813,7 @@ _popupcontextmenu(NPP instance, NPMenu* menu)
if (success) {
return mozilla::plugins::PluginUtilsOSX::ShowCocoaContextMenu(menu,
screenX, screenY,
PluginModuleChild::GetChrome(),
InstCast(instance)->Manager(),
ProcessBrowserEvents);
} else {
NS_WARNING("Convertpoint failed, could not created contextmenu.");
@@ -1978,6 +1972,29 @@ CreateFileAHookFn(LPCSTR fname, DWORD access, DWORD share,
ftemplate);
}
static bool
GetLocalLowTempPath(size_t aLen, LPWSTR aPath)
{
NS_NAMED_LITERAL_STRING(tempname, "\\Temp");
LPWSTR path;
if (SUCCEEDED(WinUtils::SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0,
nullptr, &path))) {
if (wcslen(path) + tempname.Length() < aLen) {
wcscpy(aPath, path);
wcscat(aPath, tempname.get());
::CoTaskMemFree(path);
return true;
}
::CoTaskMemFree(path);
}
// XP doesn't support SHGetKnownFolderPath and LocalLow
if (!GetTempPathW(aLen, aPath)) {
return false;
}
return true;
}
HANDLE WINAPI
CreateFileWHookFn(LPCWSTR fname, DWORD access, DWORD share,
LPSECURITY_ATTRIBUTES security, DWORD creation, DWORD flags,
@@ -1997,7 +2014,7 @@ CreateFileWHookFn(LPCWSTR fname, DWORD access, DWORD share,
// This is the config file we want to rewrite
WCHAR tempPath[MAX_PATH+1];
if (GetTempPathW(MAX_PATH, tempPath) == 0) {
if (GetLocalLowTempPath(MAX_PATH, tempPath) == 0) {
break;
}
WCHAR tempFile[MAX_PATH+1];
@@ -2170,6 +2187,17 @@ private:
NPError mResult;
};
static void
RunAsyncNPP_New(void* aChildInstance)
{
MOZ_ASSERT(aChildInstance);
PluginInstanceChild* childInstance =
static_cast<PluginInstanceChild*>(aChildInstance);
NPError rv = childInstance->DoNPP_New();
AsyncNewResultSender* task = new AsyncNewResultSender(childInstance, rv);
childInstance->PostChildAsyncCall(task);
}
bool
PluginModuleChild::RecvAsyncNPP_New(PPluginInstanceChild* aActor)
{
@@ -2177,9 +2205,8 @@ PluginModuleChild::RecvAsyncNPP_New(PPluginInstanceChild* aActor)
PluginInstanceChild* childInstance =
reinterpret_cast<PluginInstanceChild*>(aActor);
AssertPluginThread();
NPError rv = childInstance->DoNPP_New();
AsyncNewResultSender* task = new AsyncNewResultSender(childInstance, rv);
childInstance->PostChildAsyncCall(task);
// We don't want to run NPP_New async from within nested calls
childInstance->AsyncCall(&RunAsyncNPP_New, childInstance);
return true;
}
+21 -8
View File
@@ -67,14 +67,15 @@ AddSandboxAllowedFile(vector<std::wstring>& aAllowedFiles, nsIProperties* aDirSv
if (!aSuffix.IsEmpty()) {
userDirPath.Append(aSuffix);
}
aAllowedFiles.push_back(userDirPath.get());
aAllowedFiles.push_back(std::wstring(userDirPath.get()));
return;
}
static void
AddSandboxAllowedFiles(int32_t aSandboxLevel,
vector<std::wstring>& aAllowedFilesRead,
vector<std::wstring>& aAllowedFilesReadWrite)
vector<std::wstring>& aAllowedFilesReadWrite,
vector<std::wstring>& aAllowedDirectories)
{
if (aSandboxLevel < 2) {
return;
@@ -95,18 +96,27 @@ AddSandboxAllowedFiles(int32_t aSandboxLevel,
}
// Level 2 and above is now using low integrity, so we need to give write
// access to the Flash directories.
// access to the Flash directories. Access also has to be given to create
// the parent directories as they may not exist.
// This should be made Flash specific (Bug 1171396).
AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Macromedia\\Flash Player\\*"));
AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Macromedia\\Flash Player"));
AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Macromedia"));
AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Adobe\\Flash Player\\*"));
AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Adobe\\Flash Player"));
AddSandboxAllowedFile(aAllowedDirectories, dirSvc, NS_WIN_APPDATA_DIR,
NS_LITERAL_STRING("\\Adobe"));
#if defined(_X86_)
// Write access to the Temp directory should only be needed for 32-bit as
// it is used to turn off protected mode, which only applies to x86.
// Write access to the Temp directory is needed in some mochitest crash
// tests.
// Bug 1171393 tracks removing this requirement.
AddSandboxAllowedFile(aAllowedFilesReadWrite, dirSvc, NS_OS_TEMP_DIR,
NS_LITERAL_STRING("\\*"));
#endif
}
#endif
@@ -117,7 +127,7 @@ PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchComple
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
mSandboxLevel = aSandboxLevel;
AddSandboxAllowedFiles(mSandboxLevel, mAllowedFilesRead,
mAllowedFilesReadWrite);
mAllowedFilesReadWrite, mAllowedDirectories);
#else
if (aSandboxLevel != 0) {
MOZ_ASSERT(false,
@@ -153,6 +163,9 @@ PluginProcessParent::Launch(mozilla::UniquePtr<LaunchCompleteTask> aLaunchComple
else if (base::PROCESS_ARCH_ARM & pluginLibArchitectures & containerArchitectures) {
selectedArchitecture = base::PROCESS_ARCH_ARM;
}
else if (base::PROCESS_ARCH_MIPS & pluginLibArchitectures & containerArchitectures) {
selectedArchitecture = base::PROCESS_ARCH_MIPS;
}
else {
return false;
}
@@ -166,6 +166,15 @@ PluginScriptableObjectParent::ScriptableDeallocate(NPObject* aObject)
}
ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
if (object->asyncWrapperCount > 0) {
// In this case we should just drop the refcount to the asyncWrapperCount
// instead of deallocating because there are still some async wrappers
// out there that are referencing this object.
object->referenceCount = object->asyncWrapperCount;
return;
}
PluginScriptableObjectParent* actor = object->parent;
if (actor) {
NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
@@ -22,12 +22,17 @@ class PluginScriptableObjectParent;
struct ParentNPObject : NPObject
{
ParentNPObject()
: NPObject(), parent(nullptr), invalidated(false) { }
: NPObject()
, parent(nullptr)
, invalidated(false)
, asyncWrapperCount(0)
{}
// |parent| is always valid as long as the actor is alive. Once the actor is
// destroyed this will be set to null.
PluginScriptableObjectParent* parent;
bool invalidated;
int32_t asyncWrapperCount;
};
class PluginScriptableObjectParent : public PPluginScriptableObjectParent
-2
View File
@@ -772,8 +772,6 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
// set up our our instance data
InstanceData* instanceData = new InstanceData;
if (!instanceData)
return NPERR_OUT_OF_MEMORY_ERROR;
instanceData->npp = instance;
instanceData->streamMode = NP_ASFILEONLY;
instanceData->testFunction = FUNCTION_NONE;
@@ -175,9 +175,6 @@ MulticastDNSDeviceProvider::Init()
}
mWrappedListener = new DNSServiceWrappedListener();
if (NS_WARN_IF(!mWrappedListener)) {
return NS_ERROR_OUT_OF_MEMORY;
}
if (NS_WARN_IF(NS_FAILED(rv = mWrappedListener->SetListener(this)))) {
return rv;
}
-8
View File
@@ -50,8 +50,6 @@ nsXBLProtoImplMethod::AppendBodyText(const nsAString& aText)
nsXBLUncompiledMethod* uncompiledMethod = GetUncompiledMethod();
if (!uncompiledMethod) {
uncompiledMethod = new nsXBLUncompiledMethod();
if (!uncompiledMethod)
return;
SetUncompiledMethod(uncompiledMethod);
}
@@ -72,8 +70,6 @@ nsXBLProtoImplMethod::AddParameter(const nsAString& aText)
nsXBLUncompiledMethod* uncompiledMethod = GetUncompiledMethod();
if (!uncompiledMethod) {
uncompiledMethod = new nsXBLUncompiledMethod();
if (!uncompiledMethod)
return;
SetUncompiledMethod(uncompiledMethod);
}
@@ -89,8 +85,6 @@ nsXBLProtoImplMethod::SetLineNumber(uint32_t aLineNumber)
nsXBLUncompiledMethod* uncompiledMethod = GetUncompiledMethod();
if (!uncompiledMethod) {
uncompiledMethod = new nsXBLUncompiledMethod();
if (!uncompiledMethod)
return;
SetUncompiledMethod(uncompiledMethod);
}
@@ -168,8 +162,6 @@ nsXBLProtoImplMethod::CompileMember(AutoJSAPI& jsapi, const nsString& aClassStr,
char** args = nullptr;
if (paramCount > 0) {
args = new char*[paramCount];
if (!args)
return NS_ERROR_OUT_OF_MEMORY;
// Add our parameters to our args array.
int32_t argPos = 0;
-2
View File
@@ -65,8 +65,6 @@ struct nsXBLUncompiledMethod {
void AddParameter(const nsAString& aText) {
nsXBLParameter* param = new nsXBLParameter(aText);
if (!param)
return;
if (!mParameters)
mParameters = param;
else
-3
View File
@@ -197,9 +197,6 @@ void
nsXBLResourceLoader::AddResource(nsIAtom* aResourceType, const nsAString& aSrc)
{
nsXBLResource* res = new nsXBLResource(aResourceType, aSrc);
if (!res)
return;
if (!mResourceList)
mResourceList = res;
else
+2 -2
View File
@@ -165,7 +165,7 @@ AndroidSurfaceTexture::Init(GLContext* aContext, GLuint aTexture)
return false;
}
mNativeWindow = AndroidNativeWindow::CreateFromSurface(GetJNIForThread(),
mNativeWindow = AndroidNativeWindow::CreateFromSurface(jni::GetEnvForThread(),
mSurface.Get());
MOZ_ASSERT(mNativeWindow, "Failed to create native window from surface");
@@ -206,7 +206,7 @@ AndroidSurfaceTexture::UpdateTexImage()
void
AndroidSurfaceTexture::GetTransformMatrix(gfx::Matrix4x4& aMatrix)
{
JNIEnv* env = GetJNIForThread();
JNIEnv* const env = jni::GetEnvForThread();
auto jarray = FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
mSurfaceTexture->GetTransformMatrix(jarray);
+1
View File
@@ -295,6 +295,7 @@ private:
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.print-histogram", FPSPrintHistogram, bool, false);
DECL_GFX_PREF(Live, "layers.acceleration.draw-fps.write-to-file", WriteFPSToFile, bool, false);
DECL_GFX_PREF(Once, "layers.acceleration.force-enabled", LayersAccelerationForceEnabled, bool, false);
DECL_GFX_PREF(Once, "layers.amd-switchable-gfx.enabled", LayersAMDSwitchableGfxEnabled, bool, false);
DECL_GFX_PREF(Once, "layers.async-pan-zoom.enabled", AsyncPanZoomEnabledDoNotUseDirectly, bool, true);
DECL_GFX_PREF(Once, "layers.async-pan-zoom.separate-event-thread", AsyncPanZoomSeparateEventThread, bool, false);
DECL_GFX_PREF(Live, "layers.bench.enabled", LayersBenchEnabled, bool, false);
+35 -4
View File
@@ -16,6 +16,7 @@
#include "gfxFontConstants.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "mozilla/gfx/2D.h"
#include "gfxPlatformFontList.h"
@@ -433,6 +434,8 @@ gfxUserFontEntry::LoadNextSrc()
gfxUserFontData::kUnknownCompression);
mPlatformFontEntry = fe;
SetLoadState(STATUS_LOADED);
Telemetry::Accumulate(Telemetry::WEBFONT_SRCTYPE,
currSrc.mSourceType + 1);
return;
} else {
LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n",
@@ -463,6 +466,14 @@ gfxUserFontEntry::LoadNextSrc()
if (fe) {
mPlatformFontEntry = fe;
SetLoadState(STATUS_LOADED);
if (LOG_ENABLED()) {
nsAutoCString fontURI;
currSrc.mURI->GetSpec(fontURI);
LOG(("userfonts (%p) [src %d] "
"loaded uri from cache: (%s) for (%s)\n",
mFontSet, mSrcIndex, fontURI.get(),
NS_ConvertUTF16toUTF8(mFamilyName).get()));
}
return;
}
}
@@ -488,6 +499,8 @@ gfxUserFontEntry::LoadNextSrc()
if (NS_SUCCEEDED(rv) &&
LoadPlatformFont(buffer, bufferLength)) {
SetLoadState(STATUS_LOADED);
Telemetry::Accumulate(Telemetry::WEBFONT_SRCTYPE,
currSrc.mSourceType + 1);
return;
} else {
mFontSet->LogMessage(this,
@@ -542,6 +555,8 @@ gfxUserFontEntry::LoadNextSrc()
// LoadPlatformFont takes ownership of the buffer, so no need
// to free it here.
SetLoadState(STATUS_LOADED);
Telemetry::Accumulate(Telemetry::WEBFONT_SRCTYPE,
currSrc.mSourceType + 1);
return;
} else {
mFontSet->LogMessage(this,
@@ -583,6 +598,7 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
gfxUserFontType fontType =
gfxFontUtils::DetermineFontDataType(aFontData, aLength);
Telemetry::Accumulate(Telemetry::WEBFONT_FONTTYPE, uint32_t(fontType));
// Unwrap/decompress/sanitize or otherwise munge the downloaded data
// to make a usable sfnt structure.
@@ -595,12 +611,24 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
// Call the OTS sanitizer; this will also decode WOFF to sfnt
// if necessary. The original data in aFontData is left unchanged.
uint32_t saneLen;
uint32_t fontCompressionRatio = 0;
const uint8_t* saneData =
SanitizeOpenTypeData(aFontData, aLength, saneLen, fontType);
if (!saneData) {
mFontSet->LogMessage(this, "rejected by sanitizer");
}
if (saneData) {
if (saneLen) {
fontCompressionRatio = uint32_t(100.0 * aLength / saneLen + 0.5);
if (fontType == GFX_USERFONT_WOFF ||
fontType == GFX_USERFONT_WOFF2) {
Telemetry::Accumulate(fontType == GFX_USERFONT_WOFF ?
Telemetry::WEBFONT_COMPRESSION_WOFF :
Telemetry::WEBFONT_COMPRESSION_WOFF2,
fontCompressionRatio);
}
}
// The sanitizer ensures that we have a valid sfnt and a usable
// name table, so this should never fail unless we're out of
// memory, and GetFullNameFromSFNT is not directly exposed to
@@ -647,11 +675,11 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
if (LOG_ENABLED()) {
nsAutoCString fontURI;
mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) (%p) gen: %8.8x\n",
LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) "
"(%p) gen: %8.8x compress: %d%%\n",
mFontSet, mSrcIndex, fontURI.get(),
NS_ConvertUTF16toUTF8(mFamilyName).get(),
this,
uint32_t(mFontSet->mGeneration)));
this, uint32_t(mFontSet->mGeneration), fontCompressionRatio));
}
mPlatformFontEntry = fe;
SetLoadState(STATUS_LOADED);
@@ -744,7 +772,10 @@ gfxUserFontEntry::GetUserFontSets(nsTArray<gfxUserFontSet*>& aResult)
}
gfxUserFontSet::gfxUserFontSet()
: mFontFamilies(4), mLocalRulesUsed(false)
: mFontFamilies(4),
mLocalRulesUsed(false),
mDownloadCount(0),
mDownloadSize(0)
{
IncrementGeneration(true);
gfxPlatformFontList* fp = gfxPlatformFontList::PlatformFontList();
+13
View File
@@ -468,6 +468,15 @@ public:
static mozilla::LogModule* GetUserFontsLog();
// record statistics about font completion
virtual void RecordFontLoadDone(uint32_t aFontSize,
mozilla::TimeStamp aDoneTime) {}
void GetLoadStatistics(uint32_t& aLoadCount, uint64_t& aLoadSize) const {
aLoadCount = mDownloadCount;
aLoadSize = mDownloadSize;
}
protected:
// Protected destructor, to discourage deletion outside of Release():
virtual ~gfxUserFontSet();
@@ -513,6 +522,10 @@ protected:
// true when local names have been looked up, false otherwise
bool mLocalRulesUsed;
// performance stats
uint32_t mDownloadCount;
uint64_t mDownloadSize;
};
// acts a placeholder until the real font is downloaded
-22
View File
@@ -184,28 +184,6 @@ gfxWindowsNativeDrawing::BeginNativeDrawing()
}
}
bool
gfxWindowsNativeDrawing::IsDoublePass()
{
if (mContext->GetDrawTarget()->GetBackendType() != mozilla::gfx::BackendType::CAIRO ||
mContext->GetDrawTarget()->IsDualDrawTarget()) {
return true;
}
RefPtr<gfxASurface> surf = mContext->CurrentSurface(&mDeviceOffset.x, &mDeviceOffset.y);
if (!surf || surf->CairoStatus())
return false;
if (surf->GetType() != gfxSurfaceType::Win32 &&
surf->GetType() != gfxSurfaceType::Win32Printing) {
return true;
}
if ((surf->GetContentType() != gfxContentType::COLOR ||
(surf->GetContentType() == gfxContentType::COLOR_ALPHA &&
!(mNativeDrawFlags & CAN_DRAW_TO_COLOR_ALPHA))))
return true;
return false;
}
bool
gfxWindowsNativeDrawing::ShouldRenderAgain()
{
-3
View File
@@ -79,9 +79,6 @@ public:
/* Returns true if the native drawing should be executed again */
bool ShouldRenderAgain();
/* Returns true if double pass alpha extraction is taking place. */
bool IsDoublePass();
/* Places the result to the context, if necessary */
void PaintToContext();
+55 -12
View File
@@ -1682,7 +1682,7 @@ gfxWindowsPlatform::GetDXGIAdapter()
return mAdapter;
}
bool DoesD3D11DeviceWork(ID3D11Device *device)
bool DoesD3D11DeviceWork()
{
static bool checked = false;
static bool result = false;
@@ -1840,7 +1840,11 @@ bool DoesRenderTargetViewNeedsRecreating(ID3D11Device *device)
deviceContext->CopyResource(cpuTexture, offscreenTexture);
D3D11_MAPPED_SUBRESOURCE mapped;
deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped);
hr = deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped);
if (FAILED(hr)) {
gfxCriticalNote << "DoesRecreatingMapFailed " << hexa(hr);
return false;
}
int resultColor = *(int*)mapped.pData;
deviceContext->Unmap(cpuTexture, 0);
cpuTexture->Release();
@@ -1859,6 +1863,22 @@ bool DoesRenderTargetViewNeedsRecreating(ID3D11Device *device)
return result;
}
static bool TryCreateTexture2D(ID3D11Device *device,
D3D11_TEXTURE2D_DESC* desc,
D3D11_SUBRESOURCE_DATA* data,
RefPtr<ID3D11Texture2D>& texture)
{
// Older Intel driver version (see bug 1221348 for version #s) crash when
// creating a texture with shared keyed mutex and data.
MOZ_SEH_TRY {
return !FAILED(device->CreateTexture2D(desc, data, getter_AddRefs(texture)));
} MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
// For now we want to aggregrate all the crash signature to a known crash.
MOZ_CRASH("Crash creating texture. See bug 1221348.");
return false;
}
}
// See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails
// with E_OUTOFMEMORY.
@@ -1883,6 +1903,9 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
gfxInfo->GetAdapterVendorID(vendorID);
gfxInfo->GetAdapterVendorID2(vendorID2);
if (vendorID.EqualsLiteral("0x8086") && vendorID2.IsEmpty()) {
if (!gfxPrefs::LayersAMDSwitchableGfxEnabled()) {
return false;
}
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "PossiblyBrokenSurfaceSharing_UnexpectedAMDGPU";
}
}
@@ -1907,12 +1930,30 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
for (size_t i = 0; i < sizeof(color)/sizeof(color[0]); i++) {
color[i] = 0xff00ffff;
}
// We're going to check that sharing actually works with this format
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = color;
data.SysMemPitch = texture_size * 4;
data.SysMemSlicePitch = 0;
if (FAILED(device->CreateTexture2D(&desc, &data, getter_AddRefs(texture)))) {
// XXX If we pass the data directly at texture creation time we
// get a crash on Intel 8.5.10.[18xx-1994] drivers.
// We can work around this issue by doing UpdateSubresource.
if (!TryCreateTexture2D(device, &desc, nullptr, texture)) {
gfxCriticalError() << "DoesD3D11TextureSharingWork_TryCreateTextureFailure";
return false;
}
RefPtr<IDXGIKeyedMutex> sourceSharedMutex;
texture->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sourceSharedMutex));
if (FAILED(sourceSharedMutex->AcquireSync(0, 30*1000))) {
gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceMutexTimeout";
// only wait for 30 seconds
return false;
}
RefPtr<ID3D11DeviceContext> deviceContext;
device->GetImmediateContext(getter_AddRefs(deviceContext));
int stride = texture_size * 4;
deviceContext->UpdateSubresource(texture, 0, nullptr, color, stride, stride * texture_size);
if (FAILED(sourceSharedMutex->ReleaseSync(0))) {
gfxCriticalError() << "DoesD3D11TextureSharingWork_SourceReleaseSyncTimeout";
return false;
}
@@ -1921,10 +1962,12 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
if (FAILED(texture->QueryInterface(__uuidof(IDXGIResource),
getter_AddRefs(otherResource))))
{
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetResourceFailure";
return false;
}
if (FAILED(otherResource->GetSharedHandle(&shareHandle))) {
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
return false;
}
@@ -1940,6 +1983,7 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
if (FAILED(sharedResource->QueryInterface(__uuidof(ID3D11Texture2D),
getter_AddRefs(sharedTexture))))
{
gfxCriticalError() << "DoesD3D11TextureSharingWork_GetSharedTextureFailure";
return false;
}
@@ -1950,13 +1994,12 @@ bool DoesD3D11TextureSharingWorkInternal(ID3D11Device *device, DXGI_FORMAT forma
desc.MiscFlags = 0;
desc.BindFlags = 0;
if (FAILED(device->CreateTexture2D(&desc, nullptr, getter_AddRefs(cpuTexture)))) {
gfxCriticalError() << "DoesD3D11TextureSharingWork_CreateTextureFailure";
return false;
}
RefPtr<IDXGIKeyedMutex> sharedMutex;
RefPtr<ID3D11DeviceContext> deviceContext;
sharedResource->QueryInterface(__uuidof(IDXGIKeyedMutex), (void**)getter_AddRefs(sharedMutex));
device->GetImmediateContext(getter_AddRefs(deviceContext));
if (FAILED(sharedMutex->AcquireSync(0, 30*1000))) {
gfxCriticalError() << "DoesD3D11TextureSharingWork_AcquireSyncTimeout";
// only wait for 30 seconds
@@ -2117,7 +2160,7 @@ gfxWindowsPlatform::AttemptD3D11DeviceCreation()
gfxCriticalError() << "D3D11 device creation failed: " << hexa(hr);
return FeatureStatus::Failed;
}
if (!DoesD3D11DeviceWork(mD3D11Device)) {
if (!DoesD3D11DeviceWork()) {
mD3D11Device = nullptr;
return FeatureStatus::Blocked;
}
@@ -2651,7 +2694,7 @@ gfxWindowsPlatform::CreateD3D11DecoderDevice()
return nullptr;
}
if (FAILED(hr) || !device || !DoesD3D11DeviceWork(device)) {
if (FAILED(hr) || !device || !DoesD3D11DeviceWork()) {
return nullptr;
}
-4
View File
@@ -2,10 +2,6 @@
# 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/.
ifneq ($(dir $(PROGRAM)),./)
GENERATED_DIRS = $(dir $(PROGRAM))
endif
ifndef MOZ_WINCONSOLE
ifdef MOZ_DEBUG
MOZ_WINCONSOLE = 1
+4
View File
@@ -4,11 +4,15 @@
# 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/.
# Any changes that affect Android need to be made in pie/moz.build as well.
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
Program(CONFIG['MOZ_CHILD_PROCESS_NAME'])
SOURCES += [
'MozillaRuntimeMainAndroid.cpp',
]
DIRS += ['pie']
else:
kwargs = {
'linkage': None,
+32
View File
@@ -0,0 +1,32 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
Program(CONFIG['MOZ_CHILD_PROCESS_NAME_PIE'])
SOURCES += [
'../MozillaRuntimeMainAndroid.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
LOCAL_INCLUDES += [
'/toolkit/xre',
'/xpcom/base',
]
if CONFIG['MOZ_SANDBOX']:
USE_LIBS += [
'mozsandbox',
]
# gcc lto likes to put the top level asm in syscall.cc in a different partition
# from the function using it which breaks the build. Work around that by
# forcing there to be only one partition.
if '-flto' in CONFIG['OS_CXXFLAGS'] and not CONFIG['CLANG_CXX']:
LDFLAGS += ['--param lto-partitions=1']
LDFLAGS += ['-pie']
FAIL_ON_WARNINGS = True
+6
View File
@@ -119,6 +119,12 @@ class CommandLine {
// Append a loose value to the command line.
void AppendLooseValue(const std::wstring& value);
#if defined(OS_WIN)
void AppendLooseValue(const wchar_t* value) {
AppendLooseValue(std::wstring(value));
}
#endif
// Append the arguments from another command line to this one.
// If |include_program| is true, include |other|'s program as well.
void AppendArguments(const CommandLine& other,
+4
View File
@@ -116,6 +116,10 @@ class FilePath {
FilePath(const FilePath& that) : path_(that.path_) {}
explicit FilePath(const StringType& path) : path_(path) {}
#if defined(OS_WIN)
explicit FilePath(const wchar_t* path) : path_(path) {}
#endif
FilePath& operator=(const FilePath& that) {
path_ = that.path_;
return *this;
+4 -1
View File
@@ -71,7 +71,8 @@ enum ProcessArchitecture {
PROCESS_ARCH_I386 = 0x1,
PROCESS_ARCH_X86_64 = 0x2,
PROCESS_ARCH_PPC = 0x4,
PROCESS_ARCH_ARM = 0x8
PROCESS_ARCH_ARM = 0x8,
PROCESS_ARCH_MIPS = 0x10
};
inline ProcessArchitecture GetCurrentProcessArchitecture()
@@ -85,6 +86,8 @@ inline ProcessArchitecture GetCurrentProcessArchitecture()
currentArchitecture = base::PROCESS_ARCH_PPC;
#elif defined(ARCH_CPU_ARMEL)
currentArchitecture = base::PROCESS_ARCH_ARM;
#elif defined(ARCH_CPU_MIPS)
currentArchitecture = base::PROCESS_ARCH_MIPS;
#endif
return currentArchitecture;
}
+63 -42
View File
@@ -56,6 +56,10 @@ using mozilla::ipc::GeckoChildProcessHost;
static const int kMagicAndroidSystemPropFd = 5;
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
static const bool kLowRightsSubprocesses =
// We currently only attempt to drop privileges on gonk, because we
// have no plugins or extensions to worry about breaking.
@@ -94,11 +98,11 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
mPrivileges(aPrivileges),
mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
mProcessState(CREATING_CHANNEL),
mDelegate(nullptr),
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
mEnableSandboxLogging(false),
mSandboxLevel(0),
#endif
mDelegate(nullptr),
mChildProcessHandle(0)
#if defined(MOZ_WIDGET_COCOA)
, mChildTask(MACH_PORT_NULL)
@@ -168,7 +172,17 @@ GeckoChildProcessHost::GetPathToBinary(FilePath& exePath)
exePath = exePath.DirName();
}
#ifdef MOZ_WIDGET_ANDROID
exePath = exePath.AppendASCII("lib");
// We must use the PIE binary on 5.0 and higher
const char* processName = mozilla::AndroidBridge::Bridge()->GetAPIVersion() >= 21 ?
MOZ_CHILD_PROCESS_NAME_PIE : MOZ_CHILD_PROCESS_NAME;
exePath = exePath.AppendASCII(processName);
#else
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
#endif
}
#ifdef MOZ_WIDGET_COCOA
@@ -519,12 +533,15 @@ AddAppDirToCommandLine(std::vector<std::string>& aCmdLine)
NS_GET_IID(nsIFile),
getter_AddRefs(appDir));
if (NS_SUCCEEDED(rv)) {
#if defined(XP_WIN)
nsString path;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(appDir->GetPath(path)));
aCmdLine.AppendLooseValue(UTF8ToWide("-appdir"));
std::wstring wpath = path.get();
aCmdLine.AppendLooseValue(wpath);
#else
nsAutoCString path;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(appDir->GetNativePath(path)));
#if defined(XP_WIN)
aCmdLine.AppendLooseValue(UTF8ToWide("-appdir"));
aCmdLine.AppendLooseValue(UTF8ToWide(path.get()));
#else
aCmdLine.push_back("-appdir");
aCmdLine.push_back(path.get());
#endif
@@ -542,26 +559,27 @@ MaybeAddNsprLogFileAccess(std::vector<std::wstring>& aAllowedFilesReadWrite)
return;
}
nsCOMPtr<nsIFile> file;
nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR,
getter_AddRefs(file));
if (NS_FAILED(rv) || !file) {
NS_WARNING("Failed to get current working directory");
return;
}
nsDependentCString nsprLogFile(nsprLogFileEnv);
rv = file->AppendRelativeNativePath(nsprLogFile);
nsDependentCString nsprLogFilePath(nsprLogFileEnv);
nsCOMPtr<nsIFile> nsprLogFile;
nsresult rv = NS_NewNativeLocalFile(nsprLogFilePath, true,
getter_AddRefs(nsprLogFile));
if (NS_FAILED(rv)) {
// Not a relative path, try it as an absolute one.
rv = file->InitWithNativePath(nsprLogFile);
// Not an absolute path, try it as a relative one.
nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR,
getter_AddRefs(nsprLogFile));
if (NS_FAILED(rv) || !nsprLogFile) {
NS_WARNING("Failed to get current working directory");
return;
}
rv = nsprLogFile->AppendRelativeNativePath(nsprLogFilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
nsAutoString resolvedFilePath;
rv = file->GetPath(resolvedFilePath);
rv = nsprLogFile->GetPath(resolvedFilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
@@ -570,7 +588,7 @@ MaybeAddNsprLogFileAccess(std::vector<std::wstring>& aAllowedFilesReadWrite)
// Chromium sandbox can only allow access to fully qualified file paths. This
// only affects the environment for the child process we're about to create,
// because this will get reset to the original value in PerformAsyncLaunch.
aAllowedFilesReadWrite.push_back(resolvedFilePath.get());
aAllowedFilesReadWrite.push_back(std::wstring(resolvedFilePath.get()));
nsAutoCString resolvedEnvVar("NSPR_LOG_FILE=");
AppendUTF16toUTF8(resolvedFilePath, resolvedEnvVar);
PR_SetEnv(resolvedEnvVar.get());
@@ -624,32 +642,19 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
path += "/lib";
# endif // MOZ_WIDGET_ANDROID
const char *ld_library_path = PR_GetEnv("LD_LIBRARY_PATH");
nsCString new_ld_lib_path;
if (ld_library_path && *ld_library_path) {
new_ld_lib_path.Assign(path.get());
new_ld_lib_path.Append(':');
new_ld_lib_path.Append(ld_library_path);
newEnvVars["LD_LIBRARY_PATH"] = new_ld_lib_path.get();
} else {
newEnvVars["LD_LIBRARY_PATH"] = path.get();
}
nsCString new_ld_lib_path(path.get());
# if (MOZ_WIDGET_GTK == 3)
if (mProcessType == GeckoProcessType_Plugin) {
const char *ld_preload = PR_GetEnv("LD_PRELOAD");
nsCString new_ld_preload;
new_ld_preload.Assign(path.get());
new_ld_preload.AppendLiteral("/" DLL_PREFIX "mozgtk2" DLL_SUFFIX);
if (ld_preload && *ld_preload) {
new_ld_preload.AppendLiteral(":");
new_ld_preload.Append(ld_preload);
}
newEnvVars["LD_PRELOAD"] = new_ld_preload.get();
new_ld_lib_path.Append("/gtk2:");
new_ld_lib_path.Append(path.get());
}
# endif // MOZ_WIDGET_GTK
#endif
if (ld_library_path && *ld_library_path) {
new_ld_lib_path.Append(':');
new_ld_lib_path.Append(ld_library_path);
}
newEnvVars["LD_LIBRARY_PATH"] = new_ld_lib_path.get();
# elif OS_MACOSX
newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
@@ -665,7 +670,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
// been set up by whatever may have launched the browser.
const char* prevInterpose = PR_GetEnv("DYLD_INSERT_LIBRARIES");
nsCString interpose;
if (prevInterpose) {
if (prevInterpose && strlen(prevInterpose) > 0) {
interpose.Assign(prevInterpose);
interpose.Append(':');
}
@@ -919,6 +924,12 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
++it) {
mSandboxBroker.AllowReadWriteFile(it->c_str());
}
for (auto it = mAllowedDirectories.begin();
it != mAllowedDirectories.end();
++it) {
mSandboxBroker.AllowDirectory(it->c_str());
}
}
#endif // XP_WIN && MOZ_SANDBOX
@@ -948,6 +959,16 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
#endif
{
base::LaunchApp(cmdLine, false, false, &process);
#ifdef MOZ_SANDBOX
// We need to be able to duplicate handles to non-sandboxed content
// processes, so add it as a target peer.
if (mProcessType == GeckoProcessType_Content) {
if (!mSandboxBroker.AddTargetPeer(process)) {
NS_WARNING("Failed to add content process as target peer.");
}
}
#endif
}
#else
+1
View File
@@ -160,6 +160,7 @@ protected:
SandboxBroker mSandboxBroker;
std::vector<std::wstring> mAllowedFilesRead;
std::vector<std::wstring> mAllowedFilesReadWrite;
std::vector<std::wstring> mAllowedDirectories;
bool mEnableSandboxLogging;
int32_t mSandboxLevel;
#endif
+2 -2
View File
@@ -165,8 +165,8 @@ include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
for var in ('MOZ_CHILD_PROCESS_NAME', 'MOZ_CHILD_PROCESS_BUNDLE',
'DLL_PREFIX', 'DLL_SUFFIX'):
for var in ('MOZ_CHILD_PROCESS_NAME', 'MOZ_CHILD_PROCESS_NAME_PIE',
'MOZ_CHILD_PROCESS_BUNDLE', 'DLL_PREFIX', 'DLL_SUFFIX'):
DEFINES[var] = '"%s"' % CONFIG[var]
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
+14
View File
@@ -1088,6 +1088,20 @@ PresShell::Destroy()
LogTextPerfStats(tp, this, tp->cumulative, 0.0, eLog_totals, nullptr);
}
}
if (mPresContext) {
gfxUserFontSet* fs = mPresContext->GetUserFontSet();
if (fs) {
uint32_t fontCount;
uint64_t fontSize;
fs->GetLoadStatistics(fontCount, fontSize);
Telemetry::Accumulate(Telemetry::WEBFONT_PER_PAGE, fontCount);
Telemetry::Accumulate(Telemetry::WEBFONT_SIZE_PER_PAGE,
uint32_t(fontSize/1024));
} else {
Telemetry::Accumulate(Telemetry::WEBFONT_PER_PAGE, 0);
Telemetry::Accumulate(Telemetry::WEBFONT_SIZE_PER_PAGE, 0);
}
}
#ifdef MOZ_REFLOW_PERF
DumpReflows();
+2 -2
View File
@@ -20,7 +20,7 @@ public:
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
AsyncScrollBase(nsPoint aStartPos);
explicit AsyncScrollBase(nsPoint aStartPos);
void Update(TimeStamp aTime,
nsPoint aDestination,
@@ -87,6 +87,6 @@ protected:
nsSMILKeySpline mTimingFunctionY;
};
}
} // namespace mozilla
#endif // mozilla_layout_AsyncScrollBase_h_
+5 -1
View File
@@ -363,7 +363,11 @@ SetOpacityOnElement(nsIContent* aContent, double aOpacity)
bool
ScrollbarActivity::UpdateOpacity(TimeStamp aTime)
{
double progress = (aTime - mFadeBeginTime) / FadeDuration();
// Avoid division by zero if mScrollbarFadeDuration is zero, just jump
// to the end of the fade animation
double progress = mScrollbarFadeDuration
? ((aTime - mFadeBeginTime) / FadeDuration())
: 1.0;
double opacity = 1.0 - std::max(0.0, std::min(1.0, progress));
// 'this' may be getting destroyed during SetOpacityOnElement calls.
@@ -367,6 +367,7 @@ asserts-if(winWidget,0-3) load 499885-1.xhtml
load 501535-1.html
load 503961-1.xhtml
load 503961-2.html
load 505912-1.html
load 508168-1.html
load 508816-1.xul
load 508908-1.html
+10 -216
View File
@@ -301,8 +301,8 @@ nsPluginFrame::PrepForDrawing(nsIWidget *aWidget)
viewMan->InsertChild(view, mInnerView, nullptr, true);
mWidget->SetParent(parentWidget);
mWidget->Show(true);
mWidget->Enable(true);
mWidget->Show(true);
// Set the plugin window to have an empty clip region until we know
// what our true position, size and clip region are. These
@@ -1090,7 +1090,7 @@ void
nsPluginFrame::DidSetWidgetGeometry()
{
#if defined(XP_MACOSX)
if (mInstanceOwner) {
if (mInstanceOwner && !IsHidden()) {
mInstanceOwner->FixUpPluginWindow(nsPluginInstanceOwner::ePluginPaintEnable);
}
#else
@@ -1535,10 +1535,6 @@ nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect, const nsRect& aPluginRect)
{
#if defined(XP_MACOSX)
DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
#endif
#if defined(MOZ_WIDGET_ANDROID)
if (mInstanceOwner) {
gfxRect frameGfxRect =
@@ -1551,219 +1547,17 @@ nsPluginFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
return;
}
#endif
// Screen painting code
#if defined(XP_MACOSX)
// delegate all painting to the plugin instance.
#else
# if defined(DEBUG)
// On Desktop, we should have built a layer as we no longer support in-process
// plugins or synchronous painting. We can only get here for windowed plugins
// (which draw themselves), or via some error/unload state.
if (mInstanceOwner) {
if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics ||
mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
mInstanceOwner->GetDrawingModel() ==
NPDrawingModelInvalidatingCoreAnimation) {
int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
// Clip to the content area where the plugin should be drawn. If
// we don't do this, the plugin can draw outside its bounds.
nsIntRect contentPixels = aPluginRect.ToNearestPixels(appUnitsPerDevPixel);
nsIntRect dirtyPixels = aDirtyRect.ToOutsidePixels(appUnitsPerDevPixel);
nsIntRect clipPixels;
clipPixels.IntersectRect(contentPixels, dirtyPixels);
// Don't invoke the drawing code if the clip is empty.
if (clipPixels.IsEmpty())
return;
gfxRect nativeClipRect(clipPixels.x, clipPixels.y,
clipPixels.width, clipPixels.height);
gfxContext* ctx = aRenderingContext.ThebesContext();
gfxContextAutoSaveRestore save(ctx);
ctx->NewPath();
ctx->Rectangle(nativeClipRect);
ctx->Clip();
gfxPoint offset(contentPixels.x, contentPixels.y);
ctx->SetMatrix(
ctx->CurrentMatrix().Translate(offset));
gfxQuartzNativeDrawing nativeDrawing(aDrawTarget,
ToRect(nativeClipRect - offset));
CGContextRef cgContext = nativeDrawing.BeginNativeDrawing();
if (!cgContext) {
NS_WARNING("null CGContextRef during PaintPlugin");
return;
}
RefPtr<nsNPAPIPluginInstance> inst;
GetPluginInstance(getter_AddRefs(inst));
if (!inst) {
NS_WARNING("null plugin instance during PaintPlugin");
nativeDrawing.EndNativeDrawing();
return;
}
NPWindow* window;
mInstanceOwner->GetWindow(window);
if (!window) {
NS_WARNING("null plugin window during PaintPlugin");
nativeDrawing.EndNativeDrawing();
return;
}
NP_CGContext* cgPluginPortCopy =
static_cast<NP_CGContext*>(mInstanceOwner->GetPluginPortCopy());
if (!cgPluginPortCopy) {
NS_WARNING("null plugin port copy during PaintPlugin");
nativeDrawing.EndNativeDrawing();
return;
}
mInstanceOwner->BeginCGPaint();
if (mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreAnimation ||
mInstanceOwner->GetDrawingModel() ==
NPDrawingModelInvalidatingCoreAnimation) {
// CoreAnimation is updated, render the layer and perform a readback.
mInstanceOwner->RenderCoreAnimation(cgContext, window->width, window->height);
} else {
mInstanceOwner->Paint(nativeClipRect - offset, cgContext);
}
mInstanceOwner->EndCGPaint();
nativeDrawing.EndNativeDrawing();
} else {
gfxContext* ctx = aRenderingContext.ThebesContext();
// Translate the context:
gfxPoint devPixelPt =
nsLayoutUtils::PointToGfxPoint(aPluginRect.TopLeft(),
PresContext()->AppUnitsPerDevPixel());
gfxContextMatrixAutoSaveRestore autoSR(ctx);
ctx->SetMatrix(ctx->CurrentMatrix().Translate(devPixelPt));
// FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
// this rect is used only in the CoreGraphics drawing model
gfxRect tmpRect(0, 0, 0, 0);
mInstanceOwner->Paint(tmpRect, nullptr);
}
}
#elif defined(MOZ_X11)
if (mInstanceOwner) {
NPWindow *window;
NPWindow *window = nullptr;
mInstanceOwner->GetWindow(window);
if (window->type == NPWindowTypeDrawable) {
gfxRect frameGfxRect =
PresContext()->AppUnitsToGfxUnits(aPluginRect);
gfxRect dirtyGfxRect =
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
gfxContext* ctx = aRenderingContext.ThebesContext();
mInstanceOwner->Paint(ctx, frameGfxRect, dirtyGfxRect);
}
}
#elif defined(XP_WIN)
RefPtr<nsNPAPIPluginInstance> inst;
GetPluginInstance(getter_AddRefs(inst));
if (inst) {
gfxRect frameGfxRect =
PresContext()->AppUnitsToGfxUnits(aPluginRect);
gfxRect dirtyGfxRect =
PresContext()->AppUnitsToGfxUnits(aDirtyRect);
gfxContext *ctx = aRenderingContext.ThebesContext();
gfxMatrix currentMatrix = ctx->CurrentMatrix();
if (ctx->UserToDevicePixelSnapped(frameGfxRect, false)) {
dirtyGfxRect = ctx->UserToDevice(dirtyGfxRect);
ctx->SetMatrix(gfxMatrix());
}
dirtyGfxRect.RoundOut();
// Look if it's windowless
NPWindow *window;
mInstanceOwner->GetWindow(window);
if (window->type == NPWindowTypeDrawable) {
// the offset of the DC
nsPoint origin;
gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
if (nativeDraw.IsDoublePass()) {
// OOP plugin specific: let the shim know before we paint if we are doing a
// double pass render. If this plugin isn't oop, the register window message
// will be ignored.
NPEvent pluginEvent;
pluginEvent.event = plugins::DoublePassRenderingEvent();
pluginEvent.wParam = 0;
pluginEvent.lParam = 0;
if (pluginEvent.event)
inst->HandleEvent(&pluginEvent, nullptr);
}
do {
HDC hdc = nativeDraw.BeginNativeDrawing();
if (!hdc)
return;
RECT dest;
nativeDraw.TransformToNativeRect(frameGfxRect, dest);
RECT dirty;
nativeDraw.TransformToNativeRect(dirtyGfxRect, dirty);
window->window = hdc;
window->x = dest.left;
window->y = dest.top;
window->clipRect.left = 0;
window->clipRect.top = 0;
// if we're painting, we're visible.
window->clipRect.right = window->width;
window->clipRect.bottom = window->height;
// Windowless plugins on windows need a special event to update their location,
// see bug 135737.
//
// bug 271442: note, the rectangle we send is now purely the bounds of the plugin
// relative to the window it is contained in, which is useful for the plugin to
// correctly translate mouse coordinates.
//
// this does not mesh with the comments for bug 135737 which imply that the rectangle
// must be clipped in some way to prevent the plugin attempting to paint over areas
// it shouldn't.
//
// since the two uses of the rectangle are mutually exclusive in some cases, and
// since I don't see any incorrect painting (at least with Flash and ViewPoint -
// the originator of bug 135737), it seems that windowless plugins are not relying
// on information here for clipping their drawing, and we can safely use this message
// to tell the plugin exactly where it is in all cases.
nsIntPoint origin = GetWindowOriginInPixels(true);
nsIntRect winlessRect = nsIntRect(origin, nsIntSize(window->width, window->height));
if (!mWindowlessRect.IsEqualEdges(winlessRect)) {
mWindowlessRect = winlessRect;
WINDOWPOS winpos;
memset(&winpos, 0, sizeof(winpos));
winpos.x = mWindowlessRect.x;
winpos.y = mWindowlessRect.y;
winpos.cx = mWindowlessRect.width;
winpos.cy = mWindowlessRect.height;
// finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event
NPEvent pluginEvent;
pluginEvent.event = WM_WINDOWPOSCHANGED;
pluginEvent.wParam = 0;
pluginEvent.lParam = (LPARAM)&winpos;
inst->HandleEvent(&pluginEvent, nullptr);
}
inst->SetWindow(window);
mInstanceOwner->Paint(dirty, hdc);
nativeDraw.EndNativeDrawing();
} while (nativeDraw.ShouldRenderAgain());
nativeDraw.PaintToContext();
}
ctx->SetMatrix(currentMatrix);
MOZ_ASSERT(!window || window->type == NPWindowTypeWindow);
}
# endif
#endif
}
+33
View File
@@ -18,6 +18,7 @@
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "mozilla/Snprintf.h"
#include "mozilla/Telemetry.h"
#include "nsCORSListenerProxy.h"
#include "nsCSSParser.h"
#include "nsDeviceContext.h"
@@ -39,6 +40,7 @@
#include "nsPrintfCString.h"
#include "nsStyleSet.h"
#include "nsUTF8Utils.h"
#include "nsDOMNavigationTiming.h"
using namespace mozilla;
using namespace mozilla::css;
@@ -305,6 +307,17 @@ FontFaceSet::FindMatchingFontFaces(const nsAString& aFont,
}
}
TimeStamp
FontFaceSet::GetNavigationStartTimeStamp()
{
TimeStamp navStart;
RefPtr<nsDOMNavigationTiming> timing(mDocument->GetNavigationTiming());
if (timing) {
navStart = timing->GetNavigationStartTimeStamp();
}
return navStart;
}
already_AddRefed<Promise>
FontFaceSet::Load(JSContext* aCx,
const nsAString& aFont,
@@ -1720,6 +1733,26 @@ FontFaceSet::UserFontSet::StartLoad(gfxUserFontEntry* aUserFontEntry,
return mFontFaceSet->StartLoad(aUserFontEntry, aFontFaceSrc);
}
void
FontFaceSet::UserFontSet::RecordFontLoadDone(uint32_t aFontSize,
TimeStamp aDoneTime)
{
mDownloadCount++;
mDownloadSize += aFontSize;
Telemetry::Accumulate(Telemetry::WEBFONT_SIZE, aFontSize / 1024);
if (!mFontFaceSet) {
return;
}
TimeStamp navStart = mFontFaceSet->GetNavigationStartTimeStamp();
TimeStamp zero;
if (navStart != zero) {
Telemetry::AccumulateTimeDelta(Telemetry::WEBFONT_DOWNLOAD_TIME_AFTER_START,
navStart, aDoneTime);
}
}
/* virtual */ nsresult
FontFaceSet::UserFontSet::LogMessage(gfxUserFontEntry* aUserFontEntry,
const char* aMessage,
+5
View File
@@ -68,6 +68,9 @@ public:
virtual nsresult StartLoad(gfxUserFontEntry* aUserFontEntry,
const gfxFontFaceSrc* aFontFaceSrc) override;
void RecordFontLoadDone(uint32_t aFontSize,
mozilla::TimeStamp aDoneTime) override;
protected:
virtual bool GetPrivateBrowsing() override;
virtual nsresult SyncLoadFontData(gfxUserFontEntry* aFontToLoad,
@@ -293,6 +296,8 @@ private:
nsTArray<FontFace*>& aFontFaces,
mozilla::ErrorResult& aRv);
TimeStamp GetNavigationStartTimeStamp();
RefPtr<UserFontSet> mUserFontSet;
// The document this is a FontFaceSet for.
+11 -2
View File
@@ -13,6 +13,7 @@
#include "nsError.h"
#include "nsContentUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "FontFaceSet.h"
#include "nsPresContext.h"
#include "nsIPrincipal.h"
@@ -39,6 +40,7 @@ nsFontFaceLoader::nsFontFaceLoader(gfxUserFontEntry* aUserFontEntry,
mFontFaceSet(aFontFaceSet),
mChannel(aChannel)
{
mStartTime = TimeStamp::Now();
}
nsFontFaceLoader::~nsFontFaceLoader()
@@ -148,12 +150,17 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
mFontFaceSet->RemoveLoader(this);
TimeStamp doneTime = TimeStamp::Now();
TimeDuration downloadTime = doneTime - mStartTime;
uint32_t downloadTimeMS = uint32_t(downloadTime.ToMilliseconds());
Telemetry::Accumulate(Telemetry::WEBFONT_DOWNLOAD_TIME, downloadTimeMS);
if (LOG_ENABLED()) {
nsAutoCString fontURI;
mFontURI->GetSpec(fontURI);
if (NS_SUCCEEDED(aStatus)) {
LOG(("userfonts (%p) download completed - font uri: (%s)\n",
this, fontURI.get()));
LOG(("userfonts (%p) download completed - font uri: (%s) time: %d ms\n",
this, fontURI.get(), downloadTimeMS));
} else {
LOG(("userfonts (%p) download failed - font uri: (%s) error: %8.8x\n",
this, fontURI.get(), aStatus));
@@ -188,6 +195,8 @@ nsFontFaceLoader::OnStreamComplete(nsIStreamLoader* aLoader,
bool fontUpdate =
mUserFontEntry->FontDataDownloadComplete(aString, aStringLen, aStatus);
mFontFaceSet->GetUserFontSet()->RecordFontLoadDone(aStringLen, doneTime);
// when new font loaded, need to reflow
if (fontUpdate) {
nsTArray<gfxUserFontSet*> fontSets;
+2 -1
View File
@@ -10,6 +10,7 @@
#define nsFontFaceLoader_h_
#include "mozilla/Attributes.h"
#include "mozilla/TimeStamp.h"
#include "nsCOMPtr.h"
#include "nsIStreamLoader.h"
#include "nsIChannel.h"
@@ -55,7 +56,7 @@ private:
RefPtr<mozilla::dom::FontFaceSet> mFontFaceSet;
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsITimer> mLoadTimer;
TimeStamp mStartTime;
nsIStreamLoader* mStreamLoader;
};
@@ -205,6 +205,7 @@ EverySecondTelemetryCallback_s(nsAutoPtr<RTCStatsQueries> aQueryList) {
for (auto q = aQueryList->begin(); q != aQueryList->end(); ++q) {
PeerConnectionImpl::ExecuteStatsQuery_s(*q);
auto& r = *(*q)->report;
bool isHello = (*q)->isHello;
if (r.mInboundRTPStreamStats.WasPassed()) {
// First, get reports from a second ago, if any, for calculations below
const Sequence<RTCInboundRTPStreamStats> *lastInboundStats = nullptr;
@@ -237,9 +238,15 @@ EverySecondTelemetryCallback_s(nsAutoPtr<RTCStatsQueries> aQueryList) {
}
if (s.mMozRtt.WasPassed()) {
MOZ_ASSERT(s.mIsRemote);
Accumulate(isAudio? WEBRTC_AUDIO_QUALITY_OUTBOUND_RTT :
WEBRTC_VIDEO_QUALITY_OUTBOUND_RTT,
s.mMozRtt.Value());
ID id;
if (isAudio) {
id = isHello ? LOOP_AUDIO_QUALITY_OUTBOUND_RTT :
WEBRTC_AUDIO_QUALITY_OUTBOUND_RTT;
} else {
id = isHello ? LOOP_VIDEO_QUALITY_OUTBOUND_RTT :
WEBRTC_VIDEO_QUALITY_OUTBOUND_RTT;
}
Accumulate(id, s.mMozRtt.Value());
}
if (lastInboundStats && s.mBytesReceived.WasPassed()) {
auto& laststats = *lastInboundStats;
@@ -249,15 +256,32 @@ EverySecondTelemetryCallback_s(nsAutoPtr<RTCStatsQueries> aQueryList) {
if (lasts.mBytesReceived.WasPassed()) {
auto delta_ms = int32_t(s.mTimestamp.Value() -
lasts.mTimestamp.Value());
if (delta_ms > 0 && delta_ms < 60000) {
Accumulate(s.mIsRemote?
(isAudio? WEBRTC_AUDIO_QUALITY_OUTBOUND_BANDWIDTH_KBITS :
WEBRTC_VIDEO_QUALITY_OUTBOUND_BANDWIDTH_KBITS) :
(isAudio? WEBRTC_AUDIO_QUALITY_INBOUND_BANDWIDTH_KBITS :
WEBRTC_VIDEO_QUALITY_INBOUND_BANDWIDTH_KBITS),
((s.mBytesReceived.Value() -
lasts.mBytesReceived.Value()) * 8) / delta_ms);
// In theory we're called every second, so delta *should* be in that range.
// Small deltas could cause errors due to division
if (delta_ms > 500 && delta_ms < 60000) {
ID id;
if (s.mIsRemote) {
if (isAudio) {
id = isHello ? LOOP_AUDIO_QUALITY_OUTBOUND_BANDWIDTH_KBITS :
WEBRTC_AUDIO_QUALITY_OUTBOUND_BANDWIDTH_KBITS;
} else {
id = isHello ? LOOP_VIDEO_QUALITY_OUTBOUND_BANDWIDTH_KBITS :
WEBRTC_VIDEO_QUALITY_OUTBOUND_BANDWIDTH_KBITS;
}
} else {
if (isAudio) {
id = isHello ? LOOP_AUDIO_QUALITY_INBOUND_BANDWIDTH_KBITS :
WEBRTC_AUDIO_QUALITY_INBOUND_BANDWIDTH_KBITS;
} else {
id = isHello ? LOOP_VIDEO_QUALITY_INBOUND_BANDWIDTH_KBITS :
WEBRTC_VIDEO_QUALITY_INBOUND_BANDWIDTH_KBITS;
}
}
Accumulate(id, ((s.mBytesReceived.Value() -
lasts.mBytesReceived.Value()) * 8) / delta_ms);
}
// We could accumulate values until enough time has passed
// and then Accumulate() but this isn't that important.
}
}
}
@@ -381,6 +381,7 @@ PeerConnectionImpl::PeerConnectionImpl(const GlobalObject* aGlobal)
, mIdentity(nullptr)
#endif
, mPrivacyRequested(false)
, mIsLoop(false)
, mSTSThread(nullptr)
, mAllowIceLoopback(false)
, mAllowIceLinkLocal(false)
@@ -698,6 +699,12 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
location->Release();
CopyUTF16toUTF8(locationAStr, locationCStr);
#define HELLO_CLICKER_URL_START "https://hello.firefox.com/"
#define HELLO_INITIATOR_URL_START "about:loop"
mIsLoop = (strncmp(HELLO_CLICKER_URL_START, locationCStr.get(),
strlen(HELLO_CLICKER_URL_START)) == 0) ||
(strncmp(HELLO_INITIATOR_URL_START, locationCStr.get(),
strlen(HELLO_INITIATOR_URL_START)) == 0);
}
PR_snprintf(
@@ -2480,7 +2487,9 @@ PeerConnectionImpl::ShutdownMedia()
// End of call to be recorded in Telemetry
if (!mStartTime.IsNull()){
TimeDuration timeDelta = TimeStamp::Now() - mStartTime;
Telemetry::Accumulate(Telemetry::WEBRTC_CALL_DURATION, timeDelta.ToSeconds());
Telemetry::Accumulate(mIsLoop ? Telemetry::LOOP_CALL_DURATION :
Telemetry::WEBRTC_CALL_DURATION,
timeDelta.ToSeconds());
}
#endif
@@ -2759,10 +2768,12 @@ void PeerConnectionImpl::IceConnectionStateChange(
if (!mIceStartTime.IsNull()){
TimeDuration timeDelta = TimeStamp::Now() - mIceStartTime;
if (isSucceeded(domState)) {
Telemetry::Accumulate(Telemetry::WEBRTC_ICE_SUCCESS_TIME,
Telemetry::Accumulate(mIsLoop ? Telemetry::LOOP_ICE_SUCCESS_TIME :
Telemetry::WEBRTC_ICE_SUCCESS_TIME,
timeDelta.ToMilliseconds());
} else if (isFailed(domState)) {
Telemetry::Accumulate(Telemetry::WEBRTC_ICE_FAILURE_TIME,
Telemetry::Accumulate(mIsLoop ? Telemetry::LOOP_ICE_FAILURE_TIME :
Telemetry::WEBRTC_ICE_FAILURE_TIME,
timeDelta.ToMilliseconds());
}
}
@@ -2921,6 +2932,7 @@ PeerConnectionImpl::BuildStatsQuery_m(
query->iceStartTime = mIceStartTime;
query->failed = isFailed(mIceConnectionState);
query->isHello = mIsLoop;
// Populate SDP on main
if (query->internalStats) {
@@ -3379,8 +3391,11 @@ PeerConnectionImpl::startCallTelem() {
mStartTime = TimeStamp::Now();
// Increment session call counter
// If we want to track Loop calls independently here, we need two mConnectionCounters
int &cnt = PeerConnectionCtx::GetInstance()->mConnectionCounter;
Telemetry::GetHistogramById(Telemetry::WEBRTC_CALL_COUNT)->Subtract(cnt);
if (cnt > 0) {
Telemetry::GetHistogramById(Telemetry::WEBRTC_CALL_COUNT)->Subtract(cnt);
}
cnt++;
Telemetry::GetHistogramById(Telemetry::WEBRTC_CALL_COUNT)->Add(cnt);
}
@@ -214,6 +214,7 @@ class RTCStatsQuery {
std::string error;
// A timestamp to help with telemetry.
mozilla::TimeStamp iceStartTime;
bool isHello;
// Just for convenience, maybe integrate into the report later
bool failed;
@@ -476,6 +477,8 @@ public:
}
#endif
bool IsLoop() const { return mIsLoop; }
// this method checks to see if we've made a promise to protect media.
bool PrivacyRequested() const { return mPrivacyRequested; }
@@ -741,6 +744,7 @@ private:
// A name for this PC that we are willing to expose to content.
std::string mName;
bool mIsLoop; // For telemetry; doesn't have to be 100% right
// The target to run stuff on
nsCOMPtr<nsIEventTarget> mSTSThread;
@@ -819,13 +819,44 @@ MOZ_IMPLICIT WebrtcGlobalChild::~WebrtcGlobalChild()
struct StreamResult {
StreamResult() : candidateTypeBitpattern(0), streamSucceeded(false) {}
uint8_t candidateTypeBitpattern;
uint32_t candidateTypeBitpattern;
bool streamSucceeded;
};
static uint32_t GetCandidateIpAndTransportMask(const RTCIceCandidateStats *cand) {
enum {
CANDIDATE_BITMASK_UDP = 1,
CANDIDATE_BITMASK_TCP = 1 << 1,
CANDIDATE_BITMASK_IPV6 = 1 << 2,
};
uint32_t res = 0;
nsAutoCString transport;
// prefer local transport for local relay candidates
if (cand->mMozLocalTransport.WasPassed()) {
transport.Assign(NS_ConvertUTF16toUTF8(cand->mMozLocalTransport.Value()));
} else {
transport.Assign(NS_ConvertUTF16toUTF8(cand->mTransport.Value()));
}
if (transport == kNrIceTransportUdp) {
res |= CANDIDATE_BITMASK_UDP;
} else if (transport == kNrIceTransportTcp) {
res |= CANDIDATE_BITMASK_TCP;
}
if (cand->mIpAddress.Value().FindChar(':') != -1) {
res |= CANDIDATE_BITMASK_IPV6;
}
return res;
};
static void StoreLongTermICEStatisticsImpl_m(
nsresult result,
nsAutoPtr<RTCStatsQuery> query) {
nsAutoPtr<RTCStatsQuery> query,
bool aIsLoop) {
using namespace Telemetry;
@@ -837,17 +868,6 @@ static void StoreLongTermICEStatisticsImpl_m(
query->report->mClosed.Construct(true);
// First, store stuff in telemetry
enum {
REMOTE_GATHERED_SERVER_REFLEXIVE = 1,
REMOTE_GATHERED_TURN = 1 << 1,
LOCAL_GATHERED_SERVER_REFLEXIVE = 1 << 2,
LOCAL_GATHERED_TURN_UDP = 1 << 3,
LOCAL_GATHERED_TURN_TCP = 1 << 4,
LOCAL_GATHERED_TURN_TLS = 1 << 5,
LOCAL_GATHERED_TURN_HTTPS = 1 << 6,
};
// TODO(bcampen@mozilla.com): Do we need to watch out for cases where the
// components within a stream didn't have the same types of relayed
// candidates? I have a feeling that late trickle could cause this, but right
@@ -886,51 +906,74 @@ static void StoreLongTermICEStatisticsImpl_m(
if (!cand.mType.WasPassed() ||
!cand.mCandidateType.WasPassed() ||
!cand.mTransport.WasPassed() ||
!cand.mIpAddress.WasPassed() ||
!cand.mComponentId.WasPassed()) {
// Crash on debug, ignore this candidate otherwise.
MOZ_CRASH();
continue;
}
/* The bitmask after examaning a candidate should look like this:
* REMOTE_GATHERED_HOST_UDP = 1,
* REMOTE_GATHERED_HOST_TCP = 1 << 1,
* REMOTE_GATHERED_HOST_IPV6 = 1 << 2,
* REMOTE_GATHERED_SERVER_REFLEXIVE_UDP = 1 << 3,
* REMOTE_GATHERED_SERVER_REFLEXIVE_TCP = 1 << 4,
* REMOTE_GATHERED_SERVER_REFLEXIVE_IPV6 = 1 << 5,
* REMOTE_GATHERED_TURN_UDP = 1 << 6,
* REMOTE_GATHERED_TURN_TCP = 1 << 7, // dummy place holder
* REMOTE_GATHERED_TURN_IPV6 = 1 << 8,
* REMOTE_GATHERED_PEER_REFLEXIVE_UDP = 1 << 9,
* REMOTE_GATHERED_PEER_REFLEXIVE_TCP = 1 << 10,
* REMOTE_GATHERED_PEER_REFLEXIVE_IPV6 = 1 << 11,
* LOCAL_GATHERED_HOST_UDP = 1 << 16,
* LOCAL_GATHERED_HOST_TCP = 1 << 17,
* LOCAL_GATHERED_HOST_IPV6 = 1 << 18,
* LOCAL_GATHERED_SERVER_REFLEXIVE_UDP = 1 << 19,
* LOCAL_GATHERED_SERVER_REFLEXIVE_TCP = 1 << 20,
* LOCAL_GATHERED_SERVER_REFLEXIVE_IPV6 = 1 << 21,
* LOCAL_GATHERED_TURN_UDP = 1 << 22,
* LOCAL_GATHERED_TURN_TCP = 1 << 23,
* LOCAL_GATHERED_TURN_IPV6 = 1 << 24,
* LOCAL_GATHERED_PEERREFLEXIVE_UDP = 1 << 25,
* LOCAL_GATHERED_PEERREFLEXIVE_TCP = 1 << 26,
* LOCAL_GATHERED_PEERREFLEXIVE_IPV6 = 1 << 27,
*
* This results in following shift values
*/
static const uint32_t kLocalShift = 16;
static const uint32_t kSrflxShift = 3;
static const uint32_t kRelayShift = 6;
static const uint32_t kPrflxShift = 9;
uint32_t candBitmask = GetCandidateIpAndTransportMask(&cand);
// Note: shift values need to result in the above enum table
if (cand.mType.Value() == RTCStatsType::Localcandidate) {
candBitmask <<= kLocalShift;
}
if (cand.mCandidateType.Value() == RTCStatsIceCandidateType::Serverreflexive) {
candBitmask <<= kSrflxShift;
} else if (cand.mCandidateType.Value() == RTCStatsIceCandidateType::Relayed) {
candBitmask <<= kRelayShift;
} else if (cand.mCandidateType.Value() == RTCStatsIceCandidateType::Peerreflexive) {
candBitmask <<= kPrflxShift;
}
// Note: this is not a "component" in the ICE definition, this is really a
// stream ID. This is just the way the stats API is standardized right now
// stream ID. This is just the way the stats API is standardized right now.
// Very confusing.
std::string streamId(
NS_ConvertUTF16toUTF8(cand.mComponentId.Value()).get());
if (cand.mCandidateType.Value() == RTCStatsIceCandidateType::Relayed) {
if (cand.mType.Value() == RTCStatsType::Localcandidate) {
NS_ConvertUTF16toUTF8 transport(cand.mMozLocalTransport.Value());
if (transport == kNrIceTransportUdp) {
streamResults[streamId].candidateTypeBitpattern |=
LOCAL_GATHERED_TURN_UDP;
} else if (transport == kNrIceTransportTcp) {
streamResults[streamId].candidateTypeBitpattern |=
LOCAL_GATHERED_TURN_TCP;
}
} else {
streamResults[streamId].candidateTypeBitpattern |= REMOTE_GATHERED_TURN;
}
} else if (cand.mCandidateType.Value() ==
RTCStatsIceCandidateType::Serverreflexive) {
if (cand.mType.Value() == RTCStatsType::Localcandidate) {
streamResults[streamId].candidateTypeBitpattern |=
LOCAL_GATHERED_SERVER_REFLEXIVE;
} else {
streamResults[streamId].candidateTypeBitpattern |=
REMOTE_GATHERED_SERVER_REFLEXIVE;
}
}
streamResults[streamId].candidateTypeBitpattern |= candBitmask;
}
for (auto i = streamResults.begin(); i != streamResults.end(); ++i) {
if (i->second.streamSucceeded) {
Telemetry::Accumulate(Telemetry::WEBRTC_CANDIDATE_TYPES_GIVEN_SUCCESS,
i->second.candidateTypeBitpattern);
} else {
Telemetry::Accumulate(Telemetry::WEBRTC_CANDIDATE_TYPES_GIVEN_FAILURE,
i->second.candidateTypeBitpattern);
}
Telemetry::RecordWebrtcIceCandidates(i->second.candidateTypeBitpattern,
i->second.streamSucceeded, aIsLoop);
}
// Beyond ICE, accumulate telemetry for various PER_CALL settings here.
@@ -944,25 +987,30 @@ static void StoreLongTermICEStatisticsImpl_m(
continue;
}
if (s.mBitrateMean.WasPassed()) {
Accumulate(WEBRTC_VIDEO_ENCODER_BITRATE_AVG_PER_CALL_KBPS,
Accumulate(aIsLoop ? LOOP_VIDEO_ENCODER_BITRATE_AVG_PER_CALL_KBPS :
WEBRTC_VIDEO_ENCODER_BITRATE_AVG_PER_CALL_KBPS,
uint32_t(s.mBitrateMean.Value() / 1000));
}
if (s.mBitrateStdDev.WasPassed()) {
Accumulate(WEBRTC_VIDEO_ENCODER_BITRATE_STD_DEV_PER_CALL_KBPS,
Accumulate(aIsLoop? LOOP_VIDEO_ENCODER_BITRATE_STD_DEV_PER_CALL_KBPS :
WEBRTC_VIDEO_ENCODER_BITRATE_STD_DEV_PER_CALL_KBPS,
uint32_t(s.mBitrateStdDev.Value() / 1000));
}
if (s.mFramerateMean.WasPassed()) {
Accumulate(WEBRTC_VIDEO_ENCODER_FRAMERATE_AVG_PER_CALL,
Accumulate(aIsLoop ? LOOP_VIDEO_ENCODER_FRAMERATE_AVG_PER_CALL :
WEBRTC_VIDEO_ENCODER_FRAMERATE_AVG_PER_CALL,
uint32_t(s.mFramerateMean.Value()));
}
if (s.mFramerateStdDev.WasPassed()) {
Accumulate(WEBRTC_VIDEO_ENCODER_FRAMERATE_10X_STD_DEV_PER_CALL,
Accumulate(aIsLoop ? LOOP_VIDEO_ENCODER_FRAMERATE_10X_STD_DEV_PER_CALL :
WEBRTC_VIDEO_ENCODER_FRAMERATE_10X_STD_DEV_PER_CALL,
uint32_t(s.mFramerateStdDev.Value() * 10));
}
if (s.mDroppedFrames.WasPassed() && !query->iceStartTime.IsNull()) {
double mins = (TimeStamp::Now() - query->iceStartTime).ToSeconds() / 60;
if (mins > 0) {
Accumulate(WEBRTC_VIDEO_ENCODER_DROPPED_FRAMES_PER_CALL_FPM,
Accumulate(aIsLoop ? LOOP_VIDEO_ENCODER_DROPPED_FRAMES_PER_CALL_FPM :
WEBRTC_VIDEO_ENCODER_DROPPED_FRAMES_PER_CALL_FPM,
uint32_t(double(s.mDroppedFrames.Value()) / mins));
}
}
@@ -978,25 +1026,30 @@ static void StoreLongTermICEStatisticsImpl_m(
continue;
}
if (s.mBitrateMean.WasPassed()) {
Accumulate(WEBRTC_VIDEO_DECODER_BITRATE_AVG_PER_CALL_KBPS,
Accumulate(aIsLoop ? LOOP_VIDEO_DECODER_BITRATE_AVG_PER_CALL_KBPS :
WEBRTC_VIDEO_DECODER_BITRATE_AVG_PER_CALL_KBPS,
uint32_t(s.mBitrateMean.Value() / 1000));
}
if (s.mBitrateStdDev.WasPassed()) {
Accumulate(WEBRTC_VIDEO_DECODER_BITRATE_STD_DEV_PER_CALL_KBPS,
Accumulate(aIsLoop ? LOOP_VIDEO_DECODER_BITRATE_STD_DEV_PER_CALL_KBPS :
WEBRTC_VIDEO_DECODER_BITRATE_STD_DEV_PER_CALL_KBPS,
uint32_t(s.mBitrateStdDev.Value() / 1000));
}
if (s.mFramerateMean.WasPassed()) {
Accumulate(WEBRTC_VIDEO_DECODER_FRAMERATE_AVG_PER_CALL,
Accumulate(aIsLoop ? LOOP_VIDEO_DECODER_FRAMERATE_AVG_PER_CALL :
WEBRTC_VIDEO_DECODER_FRAMERATE_AVG_PER_CALL,
uint32_t(s.mFramerateMean.Value()));
}
if (s.mFramerateStdDev.WasPassed()) {
Accumulate(WEBRTC_VIDEO_DECODER_FRAMERATE_10X_STD_DEV_PER_CALL,
Accumulate(aIsLoop ? LOOP_VIDEO_DECODER_FRAMERATE_10X_STD_DEV_PER_CALL :
WEBRTC_VIDEO_DECODER_FRAMERATE_10X_STD_DEV_PER_CALL,
uint32_t(s.mFramerateStdDev.Value() * 10));
}
if (s.mDiscardedPackets.WasPassed() && !query->iceStartTime.IsNull()) {
double mins = (TimeStamp::Now() - query->iceStartTime).ToSeconds() / 60;
if (mins > 0) {
Accumulate(WEBRTC_VIDEO_DECODER_DISCARDED_PACKETS_PER_CALL_PPM,
Accumulate(aIsLoop ? LOOP_VIDEO_DECODER_DISCARDED_PACKETS_PER_CALL_PPM :
WEBRTC_VIDEO_DECODER_DISCARDED_PACKETS_PER_CALL_PPM,
uint32_t(double(s.mDiscardedPackets.Value()) / mins));
}
}
@@ -1012,7 +1065,8 @@ static void StoreLongTermICEStatisticsImpl_m(
}
static void GetStatsForLongTermStorage_s(
nsAutoPtr<RTCStatsQuery> query) {
nsAutoPtr<RTCStatsQuery> query,
bool aIsLoop) {
MOZ_ASSERT(query);
@@ -1048,13 +1102,15 @@ static void GetStatsForLongTermStorage_s(
WrapRunnableNM(
&StoreLongTermICEStatisticsImpl_m,
rv,
query),
query,
aIsLoop),
NS_DISPATCH_NORMAL);
}
void WebrtcGlobalInformation::StoreLongTermICEStatistics(
PeerConnectionImpl& aPc) {
Telemetry::Accumulate(Telemetry::WEBRTC_ICE_FINAL_CONNECTION_STATE,
Telemetry::Accumulate(aPc.IsLoop() ? Telemetry::LOOP_ICE_FINAL_CONNECTION_STATE :
Telemetry::WEBRTC_ICE_FINAL_CONNECTION_STATE,
static_cast<uint32_t>(aPc.IceConnectionState()));
if (aPc.IceConnectionState() == PCImplIceConnectionState::New) {
@@ -1071,7 +1127,7 @@ void WebrtcGlobalInformation::StoreLongTermICEStatistics(
RUN_ON_THREAD(aPc.GetSTSThread(),
WrapRunnableNM(&GetStatsForLongTermStorage_s,
query),
query, aPc.IsLoop()),
NS_DISPATCH_NORMAL);
}
+3
View File
@@ -562,6 +562,9 @@ pref("media.video_stats.enabled", true);
// Whether to enable the audio writing APIs on the audio element
pref("media.audio_data.enabled", false);
// Weather we allow AMD switchable graphics
pref("layers.amd-switchable-gfx.enabled", true);
// Whether to use async panning and zooming
pref("layers.async-pan-zoom.enabled", false);
+3 -2
View File
@@ -13,7 +13,8 @@
#include "nsThreadUtils.h"
#include "prnetdb.h"
#include "AndroidBridge.h"
#include "mozilla/jni/Utils.h"
#include "GeneratedJNIWrappers.h"
namespace mozilla {
namespace net {
@@ -80,7 +81,7 @@ Tickler::Init()
MOZ_ASSERT(!mThread);
MOZ_ASSERT(!mFD);
if (AndroidBridge::HasEnv()) {
if (jni::IsAvailable()) {
widget::GeckoAppShell::EnableNetworkNotifications();
}
@@ -223,6 +223,12 @@ SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel)
L"\\??\\pipe\\chrome.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
// Add the policy for the client side of the crash server pipe.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
// The NPAPI process needs to be able to duplicate shared memory to the
// content process and broker process, which are Section type handles.
// Content and broker are for e10s and non-e10s cases.
@@ -410,6 +416,13 @@ SandboxBroker::AllowDirectory(wchar_t const *dir)
return (sandbox::SBOX_ALL_OK == result);
}
bool
SandboxBroker::AddTargetPeer(HANDLE aPeerProcess)
{
sandbox::ResultCode result = sBrokerService->AddTargetPeer(aPeerProcess);
return (sandbox::SBOX_ALL_OK == result);
}
SandboxBroker::~SandboxBroker()
{
if (mPolicy) {
@@ -14,6 +14,7 @@
#endif
#include <stdint.h>
#include <windows.h>
namespace sandbox {
class BrokerServices;
@@ -45,6 +46,9 @@ public:
bool AllowReadWriteFile(wchar_t const *file);
bool AllowDirectory(wchar_t const *dir);
// Exposes AddTargetPeer from broker services, so that none sandboxed
// processes can be added as handle duplication targets.
bool AddTargetPeer(HANDLE aPeerProcess);
private:
static sandbox::BrokerServices *sBrokerService;
sandbox::TargetPolicy *mPolicy;
+3
View File
@@ -30,3 +30,6 @@ JAR_MANIFESTS += ['jar.mn']
with Files('**'):
BUG_COMPONENT = ('Toolkit', 'Notifications and Alerts')
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
+40 -1
View File
@@ -25,7 +25,7 @@ using namespace mozilla;
using mozilla::dom::ContentChild;
NS_IMPL_ISUPPORTS(nsAlertsService, nsIAlertsService, nsIAlertsProgressListener)
NS_IMPL_ISUPPORTS(nsAlertsService, nsIAlertsService, nsIAlertsDoNotDisturb, nsIAlertsProgressListener)
nsAlertsService::nsAlertsService()
{
@@ -150,6 +150,45 @@ NS_IMETHODIMP nsAlertsService::CloseAlert(const nsAString& aAlertName,
}
// nsIAlertsDoNotDisturb
NS_IMETHODIMP nsAlertsService::GetManualDoNotDisturb(bool* aRetVal)
{
#ifdef MOZ_WIDGET_ANDROID
return NS_ERROR_NOT_IMPLEMENTED;
#else
// Try the system notification service.
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
if (sysAlerts) {
nsCOMPtr<nsIAlertsDoNotDisturb> alertsDND(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
if (!alertsDND) {
return NS_ERROR_NOT_IMPLEMENTED;
}
return alertsDND->GetManualDoNotDisturb(aRetVal);
}
return mXULAlerts.GetManualDoNotDisturb(aRetVal);
#endif
}
NS_IMETHODIMP nsAlertsService::SetManualDoNotDisturb(bool aDoNotDisturb)
{
#ifdef MOZ_WIDGET_ANDROID
return NS_ERROR_NOT_IMPLEMENTED;
#else
// Try the system notification service.
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
if (sysAlerts) {
nsCOMPtr<nsIAlertsDoNotDisturb> alertsDND(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
if (!alertsDND) {
return NS_ERROR_NOT_IMPLEMENTED;
}
return alertsDND->SetManualDoNotDisturb(aDoNotDisturb);
}
return mXULAlerts.SetManualDoNotDisturb(aDoNotDisturb);
#endif
}
NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName,
int64_t aProgress,
int64_t aProgressMax,
@@ -28,10 +28,12 @@ typedef HRESULT (__stdcall *SHQueryUserNotificationStatePtr)(MOZ_QUERY_USER_NOTI
#endif // defined(XP_WIN)
class nsAlertsService : public nsIAlertsService,
public nsIAlertsDoNotDisturb,
public nsIAlertsProgressListener
{
public:
NS_DECL_NSIALERTSPROGRESSLISTENER
NS_DECL_NSIALERTSDONOTDISTURB
NS_DECL_NSIALERTSSERVICE
NS_DECL_ISUPPORTS
+105 -88
View File
@@ -3,7 +3,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
#include "nsIObserver.idl"
@@ -12,99 +11,117 @@ interface nsIPrincipal;
[scriptable, uuid(9d0284bf-db40-42da-8f0d-c2769dbde7aa)]
interface nsIAlertsService : nsISupports
{
/**
* Displays a sliding notification window.
*
* @param imageUrl A URL identifying the image to put in the alert.
* The OS X implemenation limits the amount of time it
* will wait for an icon to load to six seconds. After
* that time the alert will show with no icon.
* @param title The title for the alert.
* @param text The contents of the alert.
* @param textClickable If true, causes the alert text to look like a link
* and notifies the listener when user attempts to
* click the alert text.
* @param cookie A blind cookie the alert will pass back to the
* consumer during the alert listener callbacks.
* @param alertListener Used for callbacks. May be null if the caller
* doesn't care about callbacks.
* @param name The name of the notification. This is currently only
* used on Android and OS X. On Android the name is
* hashed and used as a notification ID. Notifications
* will replace previous notifications with the same name.
* @param dir Bidi override for the title. Valid values are
* "auto", "ltr" or "rtl". Only available on supported
* platforms.
* @param lang Language of title and text of the alert. Only available
* on supported platforms.
* @param inPrivateBrowsing If set to true, imageUrl will be loaded in private
* browsing mode.
* @throws NS_ERROR_NOT_AVAILABLE If the notification cannot be displayed.
*
* The following arguments will be passed to the alertListener's observe()
* method:
* subject - null
* topic - "alertfinished" when the alert goes away
* "alertclickcallback" when the text is clicked
* "alertshow" when the alert is shown
* data - the value of the cookie parameter passed to showAlertNotification.
*
* @note Depending on current circumstances (if the user's in a fullscreen
* application, for instance), the alert might not be displayed at all.
* In that case, if an alert listener is passed in it will receive the
* "alertfinished" notification immediately.
*/
void showAlertNotification(in AString imageUrl,
in AString title,
in AString text,
[optional] in boolean textClickable,
[optional] in AString cookie,
[optional] in nsIObserver alertListener,
[optional] in AString name,
[optional] in AString dir,
[optional] in AString lang,
[optional] in AString data,
[optional] in nsIPrincipal principal,
[optional] in boolean inPrivateBrowsing);
/**
* Displays a sliding notification window.
*
* @param imageUrl A URL identifying the image to put in the alert.
* The OS X implemenation limits the amount of time it
* will wait for an icon to load to six seconds. After
* that time the alert will show with no icon.
* @param title The title for the alert.
* @param text The contents of the alert.
* @param textClickable If true, causes the alert text to look like a link
* and notifies the listener when user attempts to
* click the alert text.
* @param cookie A blind cookie the alert will pass back to the
* consumer during the alert listener callbacks.
* @param alertListener Used for callbacks. May be null if the caller
* doesn't care about callbacks.
* @param name The name of the notification. This is currently only
* used on Android and OS X. On Android the name is
* hashed and used as a notification ID. Notifications
* will replace previous notifications with the same name.
* @param dir Bidi override for the title. Valid values are
* "auto", "ltr" or "rtl". Only available on supported
* platforms.
* @param lang Language of title and text of the alert. Only available
* on supported platforms.
* @param inPrivateBrowsing If set to true, imageUrl will be loaded in private
* browsing mode.
* @throws NS_ERROR_NOT_AVAILABLE If the notification cannot be displayed.
*
* The following arguments will be passed to the alertListener's observe()
* method:
* subject - null
* topic - "alertfinished" when the alert goes away
* "alertdisablecallback" when alerts should be disabled for the principal
* "alertsettingscallback" when alert settings should be opened
* "alertclickcallback" when the text is clicked
* "alertshow" when the alert is shown
* data - the value of the cookie parameter passed to showAlertNotification.
*
* @note Depending on current circumstances (if the user's in a fullscreen
* application, for instance), the alert might not be displayed at all.
* In that case, if an alert listener is passed in it will receive the
* "alertfinished" notification immediately.
*/
void showAlertNotification(in AString imageUrl,
in AString title,
in AString text,
[optional] in boolean textClickable,
[optional] in AString cookie,
[optional] in nsIObserver alertListener,
[optional] in AString name,
[optional] in AString dir,
[optional] in AString lang,
[optional] in AString data,
[optional] in nsIPrincipal principal,
[optional] in boolean inPrivateBrowsing);
/**
* Close alerts created by the service.
*
* @param name The name of the notification to close. If no name
* is provided then only a notification created with
* no name (if any) will be closed.
*/
void closeAlert([optional] in AString name,
[optional] in nsIPrincipal principal);
/**
* Close alerts created by the service.
*
* @param name The name of the notification to close. If no name
* is provided then only a notification created with
* no name (if any) will be closed.
*/
void closeAlert([optional] in AString name,
[optional] in nsIPrincipal principal);
};
[scriptable, uuid(c5d63e3a-259d-45a8-b964-8377967cb4d2)]
interface nsIAlertsDoNotDisturb : nsISupports
{
/**
* Toggles a manual Do Not Disturb mode for the service to reduce the amount
* of disruption that alerts cause the user.
* This may mean only displaying them in a notification tray/center or not
* displaying them at all. If a system backend already supports a similar
* feature controlled by the user, enabling this may not have any impact on
* code to show an alert. e.g. on OS X, the system will take care not
* disrupting a user if we simply create a notification like usual.
*/
attribute bool manualDoNotDisturb;
};
[scriptable, uuid(df1bd4b0-3a8c-40e6-806a-203f38b0bd9f)]
interface nsIAlertsProgressListener : nsISupports
{
/**
* Called to notify the alert service that progress has occurred for the
* given notification previously displayed with showAlertNotification().
*
* @param name The name of the notification displaying the
* progress. On Android the name is hashed and used
* as a notification ID.
* @param progress Numeric value in the range 0 to progressMax
* indicating the current progress.
* @param progressMax Numeric value indicating the maximum progress.
* @param text The contents of the alert. If not provided,
* the percentage will be displayed.
*/
void onProgress(in AString name,
in long long progress,
in long long progressMax,
[optional] in AString text);
/**
* Called to notify the alert service that progress has occurred for the
* given notification previously displayed with showAlertNotification().
*
* @param name The name of the notification displaying the
* progress. On Android the name is hashed and used
* as a notification ID.
* @param progress Numeric value in the range 0 to progressMax
* indicating the current progress.
* @param progressMax Numeric value indicating the maximum progress.
* @param text The contents of the alert. If not provided,
* the percentage will be displayed.
*/
void onProgress(in AString name,
in long long progress,
in long long progressMax,
[optional] in AString text);
/**
* Called to cancel and hide the given notification previously displayed
* with showAlertNotification().
*
* @param name The name of the notification.
*/
void onCancel(in AString name);
/**
* Called to cancel and hide the given notification previously displayed
* with showAlertNotification().
*
* @param name The name of the notification.
*/
void onCancel(in AString name);
};
+18
View File
@@ -48,6 +48,10 @@ nsXULAlerts::ShowAlertNotification(const nsAString& aImageUrl, const nsAString&
const nsAString& aLang, nsIPrincipal* aPrincipal,
bool aInPrivateBrowsing)
{
if (mDoNotDisturb) {
return NS_OK;
}
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
nsCOMPtr<nsISupportsArray> argsArray;
@@ -161,6 +165,20 @@ nsXULAlerts::ShowAlertNotification(const nsAString& aImageUrl, const nsAString&
return NS_OK;
}
nsresult
nsXULAlerts::SetManualDoNotDisturb(bool aDoNotDisturb)
{
mDoNotDisturb = aDoNotDisturb;
return NS_OK;
}
nsresult
nsXULAlerts::GetManualDoNotDisturb(bool* aRetVal)
{
*aRetVal = mDoNotDisturb;
return NS_OK;
}
nsresult
nsXULAlerts::CloseAlert(const nsAString& aAlertName)
{
+5
View File
@@ -29,8 +29,13 @@ public:
bool aInPrivateBrowsing);
nsresult CloseAlert(const nsAString& aAlertName);
nsresult GetManualDoNotDisturb(bool* aRetVal);
nsresult SetManualDoNotDisturb(bool aDoNotDisturb);
protected:
nsInterfaceHashtable<nsStringHashKey, nsIDOMWindow> mNamedWindows;
bool mDoNotDisturb = false;
};
/**
@@ -4,21 +4,7 @@
var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
/*
* This indicates from which corner of the screen alerts slide in,
* and from which direction (horizontal/vertical).
* 0, the default, represents bottom right, sliding vertically.
* Use any bitwise combination of the following constants:
* NS_ALERT_HORIZONTAL (1), NS_ALERT_LEFT (2), NS_ALERT_TOP (4).
*
* 6 4
* +-----------+
* 7| |5
* | |
* 3| |1
* +-----------+
* 2 0
*/
// Copied from nsILookAndFeel.h, see comments on eMetric_AlertNotificationOrigin
const NS_ALERT_HORIZONTAL = 1;
const NS_ALERT_LEFT = 2;
const NS_ALERT_TOP = 4;
@@ -229,15 +215,7 @@ function moveWindowToEnd() {
let windows = Services.wm.getEnumerator("alert:alert");
while (windows.hasMoreElements()) {
let alertWindow = windows.getNext();
let alertWindowTime = Number(
alertWindow.document.getElementById('alertTime').getAttribute('value'));
let windowTime = Number(
window.document.getElementById('alertTime').getAttribute('value'));
// The time of window creation.
// Otherwise calling the notification twice (and more) in a row
// does not work.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1263155
if ((alertWindow != window) && (alertWindowTime <= windowTime)) {
if (alertWindow != window) {
if (gOrigin & NS_ALERT_TOP) {
y = Math.max(y, alertWindow.screenY + alertWindow.outerHeight);
} else {
@@ -26,3 +26,6 @@ FINAL_LIBRARY = 'xul'
with Files('**'):
BUG_COMPONENT = ('Toolkit', 'Autocomplete')
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
@@ -44,8 +44,10 @@ NS_INTERFACE_MAP_END
nsAutoCompleteController::nsAutoCompleteController() :
mDefaultIndexCompleted(false),
mBackspaced(false),
mPopupClosedByCompositionStart(false),
mProhibitAutoFill(false),
mUserClearedAutoFill(false),
mClearingAutoFillSearchesAgain(false),
mCompositionState(eCompositionState_None),
mSearchStatus(nsAutoCompleteController::STATUS_NONE),
mRowCount(0),
@@ -119,7 +121,7 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
mSearchString = newValue;
mPlaceholderCompletionString.Truncate();
mDefaultIndexCompleted = false;
mBackspaced = false;
mProhibitAutoFill = false;
mSearchStatus = nsIAutoCompleteController::STATUS_NONE;
mRowCount = 0;
mSearchesOngoing = 0;
@@ -130,11 +132,13 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
aInput->GetSearchCount(&searchCount);
mResults.SetCapacity(searchCount);
mSearches.SetCapacity(searchCount);
mMatchCounts.SetLength(searchCount);
mImmediateSearchesCount = 0;
const char *searchCID = kAutoCompleteSearchCID;
// Since the controller can be used as a service it's important to reset this.
mClearingAutoFillSearchesAgain = false;
for (uint32_t i = 0; i < searchCount; ++i) {
// Use the search name to create the contract id string for the search service
nsAutoCString searchName;
@@ -148,12 +152,19 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
mSearches.AppendObject(search);
// Count immediate searches.
uint16_t searchType = nsIAutoCompleteSearchDescriptor::SEARCH_TYPE_DELAYED;
nsCOMPtr<nsIAutoCompleteSearchDescriptor> searchDesc =
do_QueryInterface(search);
if (searchDesc && NS_SUCCEEDED(searchDesc->GetSearchType(&searchType)) &&
searchType == nsIAutoCompleteSearchDescriptor::SEARCH_TYPE_IMMEDIATE)
mImmediateSearchesCount++;
if (searchDesc) {
uint16_t searchType = nsIAutoCompleteSearchDescriptor::SEARCH_TYPE_DELAYED;
if (NS_SUCCEEDED(searchDesc->GetSearchType(&searchType)) &&
searchType == nsIAutoCompleteSearchDescriptor::SEARCH_TYPE_IMMEDIATE) {
mImmediateSearchesCount++;
}
if (!mClearingAutoFillSearchesAgain) {
searchDesc->GetClearingAutoFillSearchesAgain(&mClearingAutoFillSearchesAgain);
}
}
}
}
@@ -199,8 +210,8 @@ nsAutoCompleteController::HandleText()
return NS_OK;
}
nsAutoString newValue;
nsCOMPtr<nsIAutoCompleteInput> input(mInput);
nsAutoString newValue;
input->GetTextValue(newValue);
// Stop all searches in case they are async.
@@ -217,25 +228,45 @@ nsAutoCompleteController::HandleText()
input->GetDisableAutoComplete(&disabled);
NS_ENSURE_TRUE(!disabled, NS_OK);
// Don't search again if the new string is the same as the last search
// Usually we don't search again if the new string is the same as the last one.
// However, if this is called immediately after compositionend event,
// we need to search the same value again since the search was canceled
// at compositionstart event handler.
if (!handlingCompositionCommit && newValue.Length() > 0 &&
newValue.Equals(mSearchString)) {
// The new string might also be the same as the last search if the autofilled
// portion was cleared. In this case, we may want to search again.
// Whether the user removed some text at the end.
bool userRemovedText =
newValue.Length() < mSearchString.Length() &&
Substring(mSearchString, 0, newValue.Length()).Equals(newValue);
// Whether the user is repeating the previous search.
bool repeatingPreviousSearch = !userRemovedText &&
newValue.Equals(mSearchString);
mUserClearedAutoFill =
repeatingPreviousSearch &&
newValue.Length() < mPlaceholderCompletionString.Length() &&
Substring(mPlaceholderCompletionString, 0, newValue.Length()).Equals(newValue);
bool searchAgainOnAutoFillClear = mUserClearedAutoFill && mClearingAutoFillSearchesAgain;
if (!handlingCompositionCommit &&
!searchAgainOnAutoFillClear &&
newValue.Length() > 0 &&
repeatingPreviousSearch) {
return NS_OK;
}
// Determine if the user has removed text from the end (probably by backspacing)
if (newValue.Length() < mSearchString.Length() &&
Substring(mSearchString, 0, newValue.Length()).Equals(newValue))
{
// We need to throw away previous results so we don't try to search through them again
ClearResults();
mBackspaced = true;
if (userRemovedText || searchAgainOnAutoFillClear) {
if (userRemovedText) {
// We need to throw away previous results so we don't try to search
// through them again.
ClearResults();
}
mProhibitAutoFill = true;
mPlaceholderCompletionString.Truncate();
} else {
mBackspaced = false;
mProhibitAutoFill = false;
}
mSearchString = newValue;
@@ -579,7 +610,7 @@ nsAutoCompleteController::HandleDelete(bool *_retval)
RowIndexToSearch(index, &searchIndex, &rowIndex);
NS_ENSURE_TRUE(searchIndex >= 0 && rowIndex >= 0, NS_ERROR_FAILURE);
nsIAutoCompleteResult *result = mResults[searchIndex];
nsIAutoCompleteResult *result = mResults.SafeObjectAt(searchIndex);
NS_ENSURE_TRUE(result, NS_ERROR_FAILURE);
nsAutoString search;
@@ -641,7 +672,7 @@ nsAutoCompleteController::GetResultAt(int32_t aIndex, nsIAutoCompleteResult** aR
RowIndexToSearch(aIndex, &searchIndex, aRowIndex);
NS_ENSURE_TRUE(searchIndex >= 0 && *aRowIndex >= 0, NS_ERROR_FAILURE);
*aResult = mResults[searchIndex];
*aResult = mResults.SafeObjectAt(searchIndex);
NS_ENSURE_TRUE(*aResult, NS_ERROR_FAILURE);
return NS_OK;
}
@@ -1133,6 +1164,13 @@ nsAutoCompleteController::StartSearch(uint16_t aSearchType)
if (NS_FAILED(rv))
return rv;
// FormFill expects the searchParam to only contain the input element id,
// other consumers may have other expectations, so this modifies it only
// for new consumers handling autoFill by themselves.
if (mProhibitAutoFill && mClearingAutoFillSearchesAgain) {
searchParam.AppendLiteral(" prohibit-autofill");
}
rv = search->StartSearch(mSearchString, searchParam, result, static_cast<nsIAutoCompleteObserver *>(this));
if (NS_FAILED(rv)) {
++mSearchesFailed;
@@ -1207,6 +1245,7 @@ nsAutoCompleteController::MaybeCompletePlaceholder()
// In addition, the selection must be at the end of the current input to
// trigger the placeholder completion.
bool usePlaceholderCompletion =
!mUserClearedAutoFill &&
!mPlaceholderCompletionString.IsEmpty() &&
mPlaceholderCompletionString.Length() > mSearchString.Length() &&
selectionEnd == selectionStart &&
@@ -1457,39 +1496,50 @@ nsresult
nsAutoCompleteController::ProcessResult(int32_t aSearchIndex, nsIAutoCompleteResult *aResult)
{
NS_ENSURE_STATE(mInput);
MOZ_ASSERT(aResult, "ProcessResult should always receive a result");
NS_ENSURE_ARG(aResult);
nsCOMPtr<nsIAutoCompleteInput> input(mInput);
uint16_t result = 0;
if (aResult)
aResult->GetSearchResult(&result);
uint16_t searchResult = 0;
aResult->GetSearchResult(&searchResult);
uint32_t oldMatchCount = 0;
uint32_t matchCount = 0;
if (aResult)
aResult->GetMatchCount(&matchCount);
int32_t resultIndex = mResults.IndexOf(aResult);
if (resultIndex == -1) {
// cache the result
mResults.AppendObject(aResult);
mMatchCounts.AppendElement(matchCount);
resultIndex = mResults.Count() - 1;
}
else {
oldMatchCount = mMatchCounts[aSearchIndex];
mMatchCounts[resultIndex] = matchCount;
// The following code supports incremental updating results in 2 ways:
// * The search may reuse the same result, just by adding entries to it.
// * The search may send a new result every time. In this case we merge
// the results and proceed on the same code path as before.
// This way both mSearches and mResults can be indexed by the search index,
// cause we'll always have only one result per search.
if (mResults.IndexOf(aResult) == -1) {
nsIAutoCompleteResult* oldResult = mResults.SafeObjectAt(aSearchIndex);
if (oldResult) {
MOZ_ASSERT(false, "Passing new matches to OnSearchResult with a new "
"nsIAutoCompleteResult every time is deprecated, please "
"update the same result until the search is done");
// Build a new nsIAutocompleteSimpleResult and merge results into it.
RefPtr<nsAutoCompleteSimpleResult> mergedResult =
new nsAutoCompleteSimpleResult();
mergedResult->AppendResult(oldResult);
mergedResult->AppendResult(aResult);
mResults.ReplaceObjectAt(mergedResult, aSearchIndex);
} else {
// This inserts and grows the array if needed.
mResults.ReplaceObjectAt(aResult, aSearchIndex);
}
}
// When found the result should have the same index as the search.
MOZ_ASSERT_IF(mResults.IndexOf(aResult) != -1,
mResults.IndexOf(aResult) == aSearchIndex);
MOZ_ASSERT(mResults.Count() >= aSearchIndex + 1,
"aSearchIndex should always be valid for mResults");
bool isTypeAheadResult = false;
if (aResult) {
aResult->GetTypeAheadResult(&isTypeAheadResult);
}
aResult->GetTypeAheadResult(&isTypeAheadResult);
if (!isTypeAheadResult) {
uint32_t oldRowCount = mRowCount;
// If the search failed, increase the match count to include the error
// description.
if (result == nsIAutoCompleteResult::RESULT_FAILURE) {
if (searchResult == nsIAutoCompleteResult::RESULT_FAILURE) {
nsAutoString error;
aResult->GetErrorDescription(error);
if (!error.IsEmpty()) {
@@ -1498,13 +1548,28 @@ nsAutoCompleteController::ProcessResult(int32_t aSearchIndex, nsIAutoCompleteRes
mTree->RowCountChanged(oldRowCount, 1);
}
}
} else if (result == nsIAutoCompleteResult::RESULT_SUCCESS ||
result == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
} else if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS ||
searchResult == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
// Increase the match count for all matches in this result.
mRowCount += matchCount - oldMatchCount;
uint32_t totalMatchCount = 0;
for (uint32_t i = 0; i < mResults.Length(); i++) {
nsIAutoCompleteResult* result = mResults.SafeObjectAt(i);
if (result) {
// not all results implement this, so it can likely fail.
bool typeAhead = false;
result->GetTypeAheadResult(&typeAhead);
if (!typeAhead) {
uint32_t matchCount = 0;
result->GetMatchCount(&matchCount);
totalMatchCount += matchCount;
}
}
}
uint32_t delta = totalMatchCount - oldRowCount;
mRowCount += delta;
if (mTree) {
mTree->RowCountChanged(oldRowCount, matchCount - oldMatchCount);
mTree->RowCountChanged(oldRowCount, delta);
}
}
@@ -1527,10 +1592,10 @@ nsAutoCompleteController::ProcessResult(int32_t aSearchIndex, nsIAutoCompleteRes
}
}
if (result == nsIAutoCompleteResult::RESULT_SUCCESS ||
result == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS ||
searchResult == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
// Try to autocomplete the default index for this search.
CompleteDefaultIndex(resultIndex);
CompleteDefaultIndex(aSearchIndex);
}
return NS_OK;
@@ -1568,7 +1633,6 @@ nsAutoCompleteController::ClearResults()
int32_t oldRowCount = mRowCount;
mRowCount = 0;
mResults.Clear();
mMatchCounts.Clear();
if (oldRowCount != 0) {
if (mTree)
mTree->RowCountChanged(0, -oldRowCount);
@@ -1588,7 +1652,7 @@ nsAutoCompleteController::ClearResults()
nsresult
nsAutoCompleteController::CompleteDefaultIndex(int32_t aResultIndex)
{
if (mDefaultIndexCompleted || mBackspaced || mSearchString.Length() == 0 || !mInput)
if (mDefaultIndexCompleted || mProhibitAutoFill || mSearchString.Length() == 0 || !mInput)
return NS_OK;
nsCOMPtr<nsIAutoCompleteInput> input(mInput);
@@ -1636,14 +1700,16 @@ nsAutoCompleteController::GetDefaultCompleteResult(int32_t aResultIndex,
// If a result index was not provided, find the first defaultIndex result.
for (int32_t i = 0; resultIndex < 0 && i < mResults.Count(); ++i) {
nsIAutoCompleteResult *result = mResults[i];
nsIAutoCompleteResult *result = mResults.SafeObjectAt(i);
if (result &&
NS_SUCCEEDED(result->GetDefaultIndex(_defaultIndex)) &&
*_defaultIndex >= 0) {
resultIndex = i;
}
}
NS_ENSURE_TRUE(resultIndex >= 0, NS_ERROR_FAILURE);
if (resultIndex < 0) {
return NS_ERROR_FAILURE;
}
*_result = mResults.SafeObjectAt(resultIndex);
NS_ENSURE_TRUE(*_result, NS_ERROR_FAILURE);
@@ -123,10 +123,8 @@ protected:
nsCOMPtr<nsIAutoCompleteInput> mInput;
nsCOMArray<nsIAutoCompleteSearch> mSearches;
// This is used as a sparse array, always use SafeObjectAt to access it.
nsCOMArray<nsIAutoCompleteResult> mResults;
// Caches the match counts for the current ongoing results to allow
// incremental results to keep the rowcount up to date.
nsTArray<uint32_t> mMatchCounts;
// Temporarily keeps the results alive while invoking startSearch() for each
// search. This is needed to allow the searches to reuse the previous result,
// since otherwise the first search clears mResults.
@@ -139,8 +137,19 @@ protected:
nsString mSearchString;
nsString mPlaceholderCompletionString;
bool mDefaultIndexCompleted;
bool mBackspaced;
bool mPopupClosedByCompositionStart;
// Whether autofill is allowed for the next search. May be retrieved by the
// search through the "prohibit-autofill" searchParam.
bool mProhibitAutoFill;
// Indicates whether the user cleared the autofilled part, returning to the
// originally entered search string.
bool mUserClearedAutoFill;
// Indicates whether clearing the autofilled string should issue a new search.
bool mClearingAutoFillSearchesAgain;
enum CompositionState {
eCompositionState_None,
eCompositionState_Composing,
@@ -4,10 +4,43 @@
#include "nsAutoCompleteSimpleResult.h"
#define CHECK_MATCH_INDEX(_index, _insert) \
if (_index < 0 || \
static_cast<MatchesArray::size_type>(_index) > mMatches.Length() || \
(!_insert && static_cast<MatchesArray::size_type>(_index) == mMatches.Length())) { \
MOZ_ASSERT(false, "Trying to use an invalid index on mMatches"); \
return NS_ERROR_ILLEGAL_VALUE; \
} \
NS_IMPL_ISUPPORTS(nsAutoCompleteSimpleResult,
nsIAutoCompleteResult,
nsIAutoCompleteSimpleResult)
struct AutoCompleteSimpleResultMatch
{
AutoCompleteSimpleResultMatch(const nsAString& aValue,
const nsAString& aComment,
const nsAString& aImage,
const nsAString& aStyle,
const nsAString& aFinalCompleteValue,
const nsAString& aLabel)
: mValue(aValue)
, mComment(aComment)
, mImage(aImage)
, mStyle(aStyle)
, mFinalCompleteValue(aFinalCompleteValue)
, mLabel(aLabel)
{
}
nsString mValue;
nsString mComment;
nsString mImage;
nsString mStyle;
nsString mFinalCompleteValue;
nsString mLabel;
};
nsAutoCompleteSimpleResult::nsAutoCompleteSimpleResult() :
mDefaultIndex(-1),
mSearchResult(RESULT_NOMATCH),
@@ -15,6 +48,74 @@ nsAutoCompleteSimpleResult::nsAutoCompleteSimpleResult() :
{
}
nsresult
nsAutoCompleteSimpleResult::AppendResult(nsIAutoCompleteResult* aResult)
{
nsAutoString searchString;
nsresult rv = aResult->GetSearchString(searchString);
NS_ENSURE_SUCCESS(rv, rv);
mSearchString = searchString;
uint16_t searchResult;
rv = aResult->GetSearchResult(&searchResult);
NS_ENSURE_SUCCESS(rv, rv);
mSearchResult = searchResult;
nsAutoString errorDescription;
if (NS_SUCCEEDED(aResult->GetErrorDescription(errorDescription)) &&
!errorDescription.IsEmpty()) {
mErrorDescription = errorDescription;
}
bool typeAheadResult = false;
if (NS_SUCCEEDED(aResult->GetTypeAheadResult(&typeAheadResult)) &&
typeAheadResult) {
mTypeAheadResult = typeAheadResult;
}
int32_t defaultIndex = -1;
if (NS_SUCCEEDED(aResult->GetDefaultIndex(&defaultIndex)) &&
defaultIndex >= 0) {
mDefaultIndex = defaultIndex;
}
nsCOMPtr<nsIAutoCompleteSimpleResult> simpleResult =
do_QueryInterface(aResult);
if (simpleResult) {
nsCOMPtr<nsIAutoCompleteSimpleResultListener> listener;
if (NS_SUCCEEDED(simpleResult->GetListener(getter_AddRefs(listener))) &&
listener) {
listener.swap(mListener);
}
}
// Copy matches.
uint32_t matchCount = 0;
rv = aResult->GetMatchCount(&matchCount);
NS_ENSURE_SUCCESS(rv, rv);
for (size_t i = 0; i < matchCount; ++i) {
nsAutoString value, comment, image, style, finalCompleteValue, label;
rv = aResult->GetValueAt(i, value);
NS_ENSURE_SUCCESS(rv, rv);
rv = aResult->GetCommentAt(i, comment);
NS_ENSURE_SUCCESS(rv, rv);
rv = aResult->GetImageAt(i, image);
NS_ENSURE_SUCCESS(rv, rv);
rv = aResult->GetStyleAt(i, style);
NS_ENSURE_SUCCESS(rv, rv);
rv = aResult->GetFinalCompleteValueAt(i, finalCompleteValue);
NS_ENSURE_SUCCESS(rv, rv);
rv = aResult->GetLabelAt(i, label);
NS_ENSURE_SUCCESS(rv, rv);
rv = AppendMatch(value, comment, image, style, finalCompleteValue, label);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
// searchString
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetSearchString(nsAString &aSearchString)
@@ -86,95 +187,85 @@ nsAutoCompleteSimpleResult::SetTypeAheadResult(bool aTypeAheadResult)
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::InsertMatchAt(int32_t aIndex,
const nsAString& aValue,
const nsAString& aComment,
const nsAString& aImage,
const nsAString& aStyle,
const nsAString& aFinalCompleteValue,
const nsAString& aLabel)
{
CHECK_MATCH_INDEX(aIndex, true);
AutoCompleteSimpleResultMatch match(aValue, aComment, aImage, aStyle, aFinalCompleteValue, aLabel);
if (!mMatches.InsertElementAt(aIndex, match)) {
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::AppendMatch(const nsAString& aValue,
const nsAString& aComment,
const nsAString& aImage,
const nsAString& aStyle,
const nsAString& aFinalCompleteValue)
const nsAString& aFinalCompleteValue,
const nsAString& aLabel)
{
CheckInvariants();
if (! mValues.AppendElement(aValue))
return NS_ERROR_OUT_OF_MEMORY;
if (! mComments.AppendElement(aComment)) {
mValues.RemoveElementAt(mValues.Length() - 1);
return NS_ERROR_OUT_OF_MEMORY;
}
if (! mImages.AppendElement(aImage)) {
mValues.RemoveElementAt(mValues.Length() - 1);
mComments.RemoveElementAt(mComments.Length() - 1);
return NS_ERROR_OUT_OF_MEMORY;
}
if (! mStyles.AppendElement(aStyle)) {
mValues.RemoveElementAt(mValues.Length() - 1);
mComments.RemoveElementAt(mComments.Length() - 1);
mImages.RemoveElementAt(mImages.Length() - 1);
return NS_ERROR_OUT_OF_MEMORY;
}
if (!mFinalCompleteValues.AppendElement(aFinalCompleteValue)) {
mValues.RemoveElementAt(mValues.Length() - 1);
mComments.RemoveElementAt(mComments.Length() - 1);
mImages.RemoveElementAt(mImages.Length() - 1);
mStyles.RemoveElementAt(mStyles.Length() - 1);
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
return InsertMatchAt(mMatches.Length(), aValue, aComment, aImage, aStyle,
aFinalCompleteValue, aLabel);
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetMatchCount(uint32_t *aMatchCount)
{
CheckInvariants();
*aMatchCount = mValues.Length();
*aMatchCount = mMatches.Length();
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetValueAt(int32_t aIndex, nsAString& _retval)
{
NS_ENSURE_TRUE(aIndex >= 0 && aIndex < int32_t(mValues.Length()),
NS_ERROR_ILLEGAL_VALUE);
CheckInvariants();
_retval = mValues[aIndex];
CHECK_MATCH_INDEX(aIndex, false);
_retval = mMatches[aIndex].mValue;
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetLabelAt(int32_t aIndex, nsAString& _retval)
{
return GetValueAt(aIndex, _retval);
CHECK_MATCH_INDEX(aIndex, false);
_retval = mMatches[aIndex].mLabel;
if (_retval.IsEmpty()) {
_retval = mMatches[aIndex].mValue;
}
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetCommentAt(int32_t aIndex, nsAString& _retval)
{
NS_ENSURE_TRUE(aIndex >= 0 && aIndex < int32_t(mComments.Length()),
NS_ERROR_ILLEGAL_VALUE);
CheckInvariants();
_retval = mComments[aIndex];
CHECK_MATCH_INDEX(aIndex, false);
_retval = mMatches[aIndex].mComment;
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetImageAt(int32_t aIndex, nsAString& _retval)
{
NS_ENSURE_TRUE(aIndex >= 0 && aIndex < int32_t(mImages.Length()),
NS_ERROR_ILLEGAL_VALUE);
CheckInvariants();
_retval = mImages[aIndex];
CHECK_MATCH_INDEX(aIndex, false);
_retval = mMatches[aIndex].mImage;
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetStyleAt(int32_t aIndex, nsAString& _retval)
{
NS_ENSURE_TRUE(aIndex >= 0 && aIndex < int32_t(mStyles.Length()),
NS_ERROR_ILLEGAL_VALUE);
CheckInvariants();
_retval = mStyles[aIndex];
CHECK_MATCH_INDEX(aIndex, false);
_retval = mMatches[aIndex].mStyle;
return NS_OK;
}
@@ -182,12 +273,11 @@ NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetFinalCompleteValueAt(int32_t aIndex,
nsAString& _retval)
{
NS_ENSURE_TRUE(aIndex >= 0 && aIndex < int32_t(mFinalCompleteValues.Length()),
NS_ERROR_ILLEGAL_VALUE);
CheckInvariants();
_retval = mFinalCompleteValues[aIndex];
if (_retval.Length() == 0)
_retval = mValues[aIndex];
CHECK_MATCH_INDEX(aIndex, false);
_retval = mMatches[aIndex].mFinalCompleteValue;
if (_retval.IsEmpty()) {
_retval = mMatches[aIndex].mValue;
}
return NS_OK;
}
@@ -198,22 +288,26 @@ nsAutoCompleteSimpleResult::SetListener(nsIAutoCompleteSimpleResultListener* aLi
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::GetListener(nsIAutoCompleteSimpleResultListener** aListener)
{
nsCOMPtr<nsIAutoCompleteSimpleResultListener> listener(mListener);
listener.forget(aListener);
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteSimpleResult::RemoveValueAt(int32_t aRowIndex,
bool aRemoveFromDb)
{
NS_ENSURE_TRUE(aRowIndex >= 0 && aRowIndex < int32_t(mValues.Length()),
NS_ERROR_ILLEGAL_VALUE);
CHECK_MATCH_INDEX(aRowIndex, false);
nsAutoString removedValue(mValues[aRowIndex]);
mValues.RemoveElementAt(aRowIndex);
mComments.RemoveElementAt(aRowIndex);
mImages.RemoveElementAt(aRowIndex);
mStyles.RemoveElementAt(aRowIndex);
mFinalCompleteValues.RemoveElementAt(aRowIndex);
nsString value = mMatches[aRowIndex].mValue;
mMatches.RemoveElementAt(aRowIndex);
if (mListener)
mListener->OnValueRemoved(this, removedValue, aRemoveFromDb);
if (mListener) {
mListener->OnValueRemoved(this, value, aRemoveFromDb);
}
return NS_OK;
}
@@ -13,34 +13,25 @@
#include "nsTArray.h"
#include "mozilla/Attributes.h"
struct AutoCompleteSimpleResultMatch;
class nsAutoCompleteSimpleResult final : public nsIAutoCompleteSimpleResult
{
public:
nsAutoCompleteSimpleResult();
inline void CheckInvariants() {
NS_ASSERTION(mValues.Length() == mComments.Length(), "Arrays out of sync");
NS_ASSERTION(mValues.Length() == mImages.Length(), "Arrays out of sync");
NS_ASSERTION(mValues.Length() == mStyles.Length(), "Arrays out of sync");
NS_ASSERTION(mValues.Length() == mFinalCompleteValues.Length(), "Arrays out of sync");
}
NS_DECL_ISUPPORTS
NS_DECL_NSIAUTOCOMPLETERESULT
NS_DECL_NSIAUTOCOMPLETESIMPLERESULT
nsresult AppendResult(nsIAutoCompleteResult* aResult);
private:
~nsAutoCompleteSimpleResult() {}
protected:
// What we really want is an array of structs with value/comment/image/style contents.
// But then we'd either have to use COM or manage object lifetimes ourselves.
// Having four arrays of string simplifies this, but is stupid.
nsTArray<nsString> mValues;
nsTArray<nsString> mComments;
nsTArray<nsString> mImages;
nsTArray<nsString> mStyles;
nsTArray<nsString> mFinalCompleteValues;
typedef nsTArray<AutoCompleteSimpleResultMatch> MatchesArray;
MatchesArray mMatches;
nsString mSearchString;
nsString mErrorDescription;
@@ -50,7 +50,7 @@ interface nsIAutoCompleteObserver : nsISupports
void onUpdateSearchResult(in nsIAutoCompleteSearch search, in nsIAutoCompleteResult result);
};
[scriptable, uuid(02314d6e-b730-40cc-a215-221554d77064)]
[scriptable, uuid(4c3e7462-fbfb-4310-8f4b-239238392b75)]
interface nsIAutoCompleteSearchDescriptor : nsISupports
{
// The search is started after the timeout specified by the corresponding
@@ -65,4 +65,10 @@ interface nsIAutoCompleteSearchDescriptor : nsISupports
* Defaults to SEARCH_TYPE_DELAYED.
*/
readonly attribute unsigned short searchType;
/*
* Whether a new search should be triggered when the user deletes the
* autofilled part.
*/
readonly attribute boolean clearingAutoFillSearchesAgain;
};
@@ -14,7 +14,7 @@ interface nsIAutoCompleteSimpleResultListener;
* an array.
*/
[scriptable, uuid(fe8802f9-c2b7-4141-8e5b-280df3f62251)]
[scriptable, uuid(23de9c96-becb-4d0d-a9bb-1d131ce361b5)]
interface nsIAutoCompleteSimpleResult : nsIAutoCompleteResult
{
/**
@@ -47,6 +47,31 @@ interface nsIAutoCompleteSimpleResult : nsIAutoCompleteResult
*/
void setTypeAheadResult(in boolean aHidden);
/**
* Inserts a match consisting of the given value, comment, image, style and
* the value to use for defaultIndex completion at a given position.
* @param aIndex
* The index to insert at
* @param aValue
* The value to autocomplete to
* @param aComment
* Comment shown in the autocomplete widget to describe this match
* @param aImage
* Image shown in the autocomplete widget for this match.
* @param aStyle
* Describes how to style the match in the autocomplete widget
* @param aFinalCompleteValue
* Value used when the user confirms selecting this match. If not
* provided, aValue will be used.
*/
void insertMatchAt(in long aIndex,
in AString aValue,
in AString aComment,
[optional] in AString aImage,
[optional] in AString aStyle,
[optional] in AString aFinalCompleteValue,
[optional] in AString aLabel);
/**
* Appends a match consisting of the given value, comment, image, style and
* the value to use for defaultIndex completion.
@@ -66,7 +91,13 @@ interface nsIAutoCompleteSimpleResult : nsIAutoCompleteResult
in AString aComment,
[optional] in AString aImage,
[optional] in AString aStyle,
[optional] in AString aFinalCompleteValue);
[optional] in AString aFinalCompleteValue,
[optional] in AString aLabel);
/**
* Gets the listener for changes in the result.
*/
nsIAutoCompleteSimpleResultListener getListener();
/**
* Sets a listener for changes in the result.
@@ -146,6 +146,7 @@ AutoCompleteResult.prototype = {
*/
function AutoCompleteSearch(aName, aResult) {
this.name = aName;
this._result = aResult;
}
AutoCompleteSearch.prototype = {
constructor: AutoCompleteSearch,
@@ -154,7 +155,7 @@ AutoCompleteSearch.prototype = {
name: null,
// AutoCompleteResult
_result:null,
_result: null,
/**
@@ -1,6 +1,3 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Search object that returns results at different times.
* First, the search that returns results asynchronously.
@@ -10,11 +7,16 @@ function AutoCompleteAsyncSearch(aName, aResult) {
this._result = aResult;
}
AutoCompleteAsyncSearch.prototype = Object.create(AutoCompleteSearchBase.prototype);
AutoCompleteAsyncSearch.prototype.startSearch = function(aSearchString,
aSearchParam,
aPreviousResult,
AutoCompleteAsyncSearch.prototype.startSearch = function(aSearchString,
aSearchParam,
aPreviousResult,
aListener) {
setTimeout(this._returnResults.bind(this), 500, aListener);
this._result.searchResult = Ci.nsIAutoCompleteResult.RESULT_NOMATCH_ONGOING;
aListener.onSearchResult(this, this._result);
do_timeout(500, () => {
this._returnResults(aListener);
});
};
AutoCompleteAsyncSearch.prototype._returnResults = function(aListener) {
@@ -32,9 +34,9 @@ function AutoCompleteSyncSearch(aName, aResult) {
this._result = aResult;
}
AutoCompleteSyncSearch.prototype = Object.create(AutoCompleteAsyncSearch.prototype);
AutoCompleteSyncSearch.prototype.startSearch = function(aSearchString,
aSearchParam,
aPreviousResult,
AutoCompleteSyncSearch.prototype.startSearch = function(aSearchString,
aSearchParam,
aPreviousResult,
aListener) {
this._returnResults(aListener);
};
@@ -49,7 +51,7 @@ function AutoCompleteResult(aValues, aDefaultIndex) {
AutoCompleteResult.prototype = Object.create(AutoCompleteResultBase.prototype);
/**
/**
* Test AutoComplete with multiple AutoCompleteSearch sources, with one of them
* (index != 0) returning before the rest.
*/
@@ -60,19 +62,19 @@ function run_test() {
var inputStr = "moz";
// Async search
var asyncSearch = new AutoCompleteAsyncSearch("Async",
var asyncSearch = new AutoCompleteAsyncSearch("Async",
new AutoCompleteResult(results, -1));
// Sync search
var syncSearch = new AutoCompleteSyncSearch("Sync",
new AutoCompleteResult(results, 0));
// Register searches so AutoCompleteController can find them
registerAutoCompleteSearch(asyncSearch);
registerAutoCompleteSearch(syncSearch);
var controller = Cc["@mozilla.org/autocomplete/controller;1"].
getService(Ci.nsIAutoCompleteController);
getService(Ci.nsIAutoCompleteController);
// Make an AutoCompleteInput that uses our searches
// and confirms results on search complete.
// Async search MUST be FIRST to trigger the bug this tests.
@@ -0,0 +1,14 @@
function run_test() {
let result = Cc["@mozilla.org/autocomplete/simple-result;1"]
.createInstance(Ci.nsIAutoCompleteSimpleResult);
result.appendMatch("a", "");
result.appendMatch("c", "");
result.insertMatchAt(1, "b", "");
result.insertMatchAt(3, "d", "");
Assert.equal(result.matchCount, 4);
Assert.equal(result.getValueAt(0), "a");
Assert.equal(result.getValueAt(1), "b");
Assert.equal(result.getValueAt(2), "c");
Assert.equal(result.getValueAt(3), "d");
}
@@ -18,6 +18,7 @@ skip-if = toolkit == 'gonk'
[test_finalDefaultCompleteValue.js]
[test_hiddenResult.js]
[test_immediate_search.js]
[test_insertMatchAt.js]
[test_popupSelectionVsDefaultCompleteValue.js]
[test_previousResult.js]
[test_stopSearch.js]
+3
View File
@@ -32,3 +32,6 @@ if not CONFIG['MOZ_DISABLE_PARENTAL_CONTROLS']:
LOCAL_INCLUDES += [
'../parentalcontrols',
]
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
@@ -28,3 +28,6 @@ FINAL_LIBRARY = 'xul'
with Files('**'):
BUG_COMPONENT = ('Toolkit', 'Startup and Profile System')
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
+3
View File
@@ -22,3 +22,6 @@ FINAL_LIBRARY = 'xul'
with Files('**'):
BUG_COMPONENT = ('Core', 'js-ctypes')
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
@@ -20,3 +20,6 @@ SharedLibrary('jsctypes-test')
LOCAL_INCLUDES += [
'/js/src/ctypes',
]
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']
@@ -21,3 +21,6 @@ SOURCES = [
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
if CONFIG['GNU_CXX']:
CXXFLAGS += ['-Wshadow']

Some files were not shown because too many files have changed in this diff Show More