Bug 785348. Part 1: Track when we've called into plugin code. While we're in plugin code, never run the refresh driver. r=mats

--HG--
extra : rebase_source : 2ddabda92acc1364d3c24cf20f7d45896ac09849
This commit is contained in:
Robert O'Callahan 2012-12-07 12:58:14 +13:00
parent 529d171a21
commit bff2be0517
5 changed files with 38 additions and 14 deletions

View File

@ -186,12 +186,20 @@ enum eNPPStreamTypeInternal {
static NS_DEFINE_IID(kMemoryCID, NS_MEMORY_CID);
PRIntervalTime NS_NotifyBeginPluginCall()
{
nsNPAPIPluginInstance::BeginPluginCall();
return PR_IntervalNow();
}
// This function sends a notification using the observer service to any object
// registered to listen to the "experimental-notify-plugin-call" subject.
// Each "experimental-notify-plugin-call" notification carries with it the run
// time value in milliseconds that the call took to execute.
void NS_NotifyPluginCall(PRIntervalTime startTime)
{
nsNPAPIPluginInstance::EndPluginCall();
PRIntervalTime endTime = PR_IntervalNow() - startTime;
nsCOMPtr<nsIObserverService> notifyUIService =
mozilla::services::GetObserverService();

View File

@ -200,6 +200,8 @@ nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
}
}
uint32_t nsNPAPIPluginInstance::gInPluginCalls = 0;
void
nsNPAPIPluginInstance::Destroy()
{

View File

@ -270,6 +270,14 @@ public:
// Returns the contents scale factor of the screen the plugin is drawn on.
double GetContentsScaleFactor();
static bool InPluginCall() { return gInPluginCalls > 0; }
static void BeginPluginCall() { ++gInPluginCalls; }
static void EndPluginCall()
{
NS_ASSERTION(InPluginCall(), "Must be in plugin call");
--gInPluginCalls;
}
protected:
nsresult GetTagType(nsPluginTagType *result);
@ -364,6 +372,8 @@ private:
// is this instance Java and affected by bug 750480?
bool mHaveJavaC2PJSObjectQuirk;
static uint32_t gInPluginCalls;
};
#endif // nsNPAPIPluginInstance_h_

View File

@ -14,6 +14,7 @@
#define CALL_SAFETY_ON
#endif
PRIntervalTime NS_NotifyBeginPluginCall();
void NS_NotifyPluginCall(PRIntervalTime);
#ifdef CALL_SAFETY_ON
@ -31,7 +32,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
if(gSkipPluginSafeCalls) \
ret = fun; \
else \
@ -40,7 +41,7 @@ PR_BEGIN_MACRO \
{ \
ret = fun; \
} \
MOZ_SEH_EXCEPT(true) \
MOZ_SEH_EXCEPT(true) \
{ \
nsresult res; \
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
@ -54,7 +55,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
if(gSkipPluginSafeCalls) \
fun; \
else \
@ -63,7 +64,7 @@ PR_BEGIN_MACRO \
{ \
fun; \
} \
MOZ_SEH_EXCEPT(true) \
MOZ_SEH_EXCEPT(true) \
{ \
nsresult res; \
nsCOMPtr<nsIPluginHost> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID, &res));\
@ -78,16 +79,16 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
ret = fun; \
NS_NotifyPluginCall(startTime); \
NS_NotifyPluginCall(startTime); \
PR_END_MACRO
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = PR_IntervalNow(); \
fun; \
NS_NotifyPluginCall(startTime); \
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
fun; \
NS_NotifyPluginCall(startTime); \
PR_END_MACRO
#endif // CALL_SAFETY_ON

View File

@ -25,9 +25,7 @@
#include "mozilla/Preferences.h"
#include "nsIViewManager.h"
#include "sampler.h"
using mozilla::TimeStamp;
using mozilla::TimeDuration;
#include "nsNPAPIPluginInstance.h"
using namespace mozilla;
@ -310,6 +308,11 @@ nsRefreshDriver::Notify(nsITimer *aTimer)
NS_PRECONDITION(mPresContext, "Why are we notified after disconnection?");
NS_PRECONDITION(!nsContentUtils::GetCurrentJSContext(),
"Shouldn't have a JSContext on the stack");
if (nsNPAPIPluginInstance::InPluginCall()) {
NS_ERROR("Refresh driver should not run during plugin call!");
// Try to survive this by just ignoring the refresh tick.
return NS_OK;
}
if (mTestControllingRefreshes && aTimer) {
// Ignore real refreshes from our timer (but honor the others).