Merge m-c to s-c

This commit is contained in:
Gregory Szorc 2011-12-14 17:29:29 -08:00
commit 6c715c1626
97 changed files with 2846 additions and 609 deletions

View File

@ -66,6 +66,7 @@ pref("image.cache.size", 1048576); // bytes
/* offline cache prefs */
pref("browser.offline-apps.notify", false);
pref("browser.cache.offline.enable", false);
/* protocol warning prefs */
pref("network.protocol-handler.warn-external.tel", false);

View File

@ -72,11 +72,19 @@ function startupHttpd(baseDir, port) {
server.start(port);
}
// XXX until we have a security model, just let the pre-installed
// app used indexedDB.
function allowIndexedDB(url) {
let uri = Services.io.newURI(url, null, null);
Services.perms.add(uri, 'indexedDB', Ci.nsIPermissionManager.ALLOW_ACTION);
// FIXME Bug 707625
// until we have a proper security model, add some rights to
// the pre-installed web applications
function addPermissions(urls) {
let permissions = ['indexedDB', 'webapps-manage', 'offline-app'];
urls.forEach(function(url) {
let uri = Services.io.newURI(url, null, null);
let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
permissions.forEach(function(permission) {
Services.perms.add(uri, permission, allow);
});
});
}
@ -135,7 +143,7 @@ var shell = {
let baseHost = 'http://localhost';
homeURL = homeURL.replace(baseDir, baseHost + ':' + SERVER_PORT);
}
allowIndexedDB(homeURL);
addPermissions([homeURL]);
} catch (e) {
let msg = 'Fatal error during startup: [' + e + '[' + homeURL + ']';
return alert(msg);
@ -172,7 +180,7 @@ var shell = {
doCommand: function shell_doCommand(cmd) {
switch (cmd) {
case 'cmd_close':
this.sendEvent(this.home.contentWindow, 'appclose');
this.home.contentWindow.postMessage('appclose', '*');
break;
}
},
@ -200,6 +208,9 @@ var shell = {
break;
case 'MozApplicationManifest':
try {
if (!Services.prefs.getBoolPref('browser.cache.offline.enable'))
return;
let contentWindow = evt.originalTarget.defaultView;
let documentElement = contentWindow.document.documentElement;
if (!documentElement)
@ -210,10 +221,18 @@ var shell = {
return;
let documentURI = contentWindow.document.documentURIObject;
let manifestURI = Services.io.newURI(manifest, null, documentURI);
if (!Services.perms.testPermission(documentURI, 'offline-app')) {
if (Services.prefs.getBoolPref('browser.offline-apps.notify')) {
// FIXME Bug 710729 - Add a UI for offline cache notifications
return;
}
return;
}
Services.perms.add(documentURI, 'offline-app',
Ci.nsIPermissionManager.ALLOW_ACTION);
let manifestURI = Services.io.newURI(manifest, null, documentURI);
let updateService = Cc['@mozilla.org/offlinecacheupdate-service;1']
.getService(Ci.nsIOfflineCacheUpdateService);
updateService.scheduleUpdate(manifestURI, documentURI, window);

View File

@ -394,7 +394,7 @@
ClearErrors
ReadRegStr $1 HKLM "Software\Classes\FirefoxHTML\ShellEx\IconHandler" ""
${Unless} ${Errors}
ReadRegStr $1 HKLM "Software\Classes\FirefoxHTML\" ""
ReadRegStr $1 HKLM "Software\Classes\FirefoxHTML\DefaultIcon" ""
${GetLongPath} "$INSTDIR\${FileMainEXE}" $2
${If} "$1" != "$2,1"
WriteRegStr HKLM "Software\Classes\FirefoxHTML\DefaultIcon" "" "$2,1"

View File

@ -398,6 +398,11 @@ user_pref("extensions.update.url", "http://%(server)s/extensions-dummy/updateURL
user_pref("extensions.blocklist.url", "http://%(server)s/extensions-dummy/blocklistURL");
// Make sure opening about:addons won't hit the network
user_pref("extensions.webservice.discoverURL", "http://%(server)s/extensions-dummy/discoveryURL");
// Make sure AddonRepository won't hit the network
user_pref("extensions.getAddons.maxResults", 0);
user_pref("extensions.getAddons.get.url", "http://%(server)s/extensions-dummy/repositoryGetURL");
user_pref("extensions.getAddons.search.browseURL", "http://%(server)s/extensions-dummy/repositoryBrowseURL");
user_pref("extensions.getAddons.search.url", "http://%(server)s/extensions-dummy/repositorySearchURL");
""" % { "server" : self.webServer + ":" + str(self.httpPort) }
prefs.append(part)

View File

@ -51,7 +51,7 @@ interface nsIDOMClientRect;
/**
* This interface represents a content node that loads objects.
*/
[scriptable, uuid(107e8048-d00f-4711-bd21-97184ccae0b1)]
[scriptable, uuid(e5330f90-91a3-41d7-b29e-af38a23a6602)]
interface nsIObjectLoadingContent : nsISupports
{
const unsigned long TYPE_LOADING = 0;
@ -125,4 +125,10 @@ interface nsIObjectLoadingContent : nsISupports
in AString pluginDumpID,
in AString browserDumpID,
in boolean submittedCrashReport);
/**
* This method will play a plugin that has been stopped by the
* click-to-play plugins feature.
*/
void playPlugin();
};

View File

@ -105,10 +105,7 @@ static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc");
#define LOG(args) PR_LOG(gObjectLog, PR_LOG_DEBUG, args)
#define LOG_ENABLED() PR_LOG_TEST(gObjectLog, PR_LOG_DEBUG)
#ifdef ANDROID
#include "nsXULAppAPI.h"
#include "mozilla/Preferences.h"
#endif
class nsAsyncInstantiateEvent : public nsRunnable {
public:
@ -428,14 +425,14 @@ IsSupportedImage(const nsCString& aMimeType)
}
static bool
IsSupportedPlugin(const nsCString& aMIMEType)
IsSupportedPlugin(const nsCString& aMIMEType, bool aShouldPlay)
{
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
return false;
}
nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get());
nsresult rv = pluginHost->IsPluginEnabledForType(aMIMEType.get(), aShouldPlay);
return NS_SUCCEEDED(rv);
}
@ -461,7 +458,7 @@ GetExtensionFromURI(nsIURI* uri, nsCString& ext)
* in the given URI. The MIME type is returned in the mimeType out parameter.
*/
static bool
IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType, bool aShouldPlay)
{
nsCAutoString ext;
GetExtensionFromURI(uri, ext);
@ -477,7 +474,8 @@ IsPluginEnabledByExtension(nsIURI* uri, nsCString& mimeType)
}
const char* typeFromExt;
if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt))) {
if (NS_SUCCEEDED(pluginHost->IsPluginEnabledForExtension(ext.get(), typeFromExt,
aShouldPlay))) {
mimeType = typeFromExt;
return true;
}
@ -492,6 +490,8 @@ nsObjectLoadingContent::nsObjectLoadingContent()
, mUserDisabled(false)
, mSuppressed(false)
, mNetworkCreated(true)
// If plugins.click_to_play is false, plugins should always play
, mShouldPlay(!mozilla::Preferences::GetBool("plugins.click_to_play", false))
, mFallbackReason(ePluginOtherState)
{
}
@ -553,7 +553,7 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
// Need to check IsSupportedPlugin() in addition to GetTypeOfContent()
// because otherwise the default plug-in's catch-all behavior would
// confuse things.
(IsSupportedPlugin(mContentType) &&
(IsSupportedPlugin(mContentType, mShouldPlay) &&
GetTypeOfContent(mContentType) == eType_Plugin)) {
// Set the type we'll use for dispatch on the channel. Otherwise we could
// end up trying to dispatch to a nsFrameLoader, which will complain that
@ -573,7 +573,7 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest,
if (mContentType.EqualsASCII(APPLICATION_OCTET_STREAM)) {
nsCAutoString extType;
if (IsPluginEnabledByExtension(uri, extType)) {
if (IsPluginEnabledByExtension(uri, extType, mShouldPlay)) {
mContentType = extType;
chan->SetContentType(extType);
}
@ -1273,8 +1273,8 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
nsCAutoString overrideType;
if ((caps & eOverrideServerType) &&
((!aTypeHint.IsEmpty() && IsSupportedPlugin(aTypeHint)) ||
(aURI && IsPluginEnabledByExtension(aURI, overrideType)))) {
((!aTypeHint.IsEmpty() && IsSupportedPlugin(aTypeHint, mShouldPlay)) ||
(aURI && IsPluginEnabledByExtension(aURI, overrideType, mShouldPlay)))) {
ObjectType newType;
if (overrideType.IsEmpty()) {
newType = GetTypeOfContent(aTypeHint);
@ -1412,7 +1412,7 @@ nsObjectLoadingContent::LoadObject(nsIURI* aURI,
return NS_OK;
}
if (IsSupportedPlugin(aTypeHint)) {
if (IsSupportedPlugin(aTypeHint, mShouldPlay)) {
mType = eType_Plugin;
rv = TryInstantiate(aTypeHint, aURI);
@ -1714,7 +1714,7 @@ nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType)
return eType_Document;
}
if ((caps & eSupportPlugins) && IsSupportedPlugin(aMIMEType)) {
if ((caps & eSupportPlugins) && IsSupportedPlugin(aMIMEType, mShouldPlay)) {
return eType_Plugin;
}
@ -1875,7 +1875,7 @@ nsObjectLoadingContent::Instantiate(nsIObjectFrame* aFrame,
nsCString typeToUse(aMIMEType);
if (typeToUse.IsEmpty() && aURI) {
IsPluginEnabledByExtension(aURI, typeToUse);
IsPluginEnabledByExtension(aURI, typeToUse, mShouldPlay);
}
nsCOMPtr<nsIContent> thisContent =
@ -1962,12 +1962,6 @@ nsObjectLoadingContent::GetPluginSupportState(nsIContent* aContent,
/* static */ PluginSupportState
nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
{
#ifdef ANDROID
// if plugins are disabled, don't show the click to play message
if (!mozilla::Preferences::GetBool("plugin.disable", false) &&
XRE_GetProcessType() == GeckoProcessType_Content)
return ePluginClickToPlay;
#endif
nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
if (!pluginHost) {
@ -1977,6 +1971,8 @@ nsObjectLoadingContent::GetPluginDisabledState(const nsCString& aContentType)
nsresult rv = pluginHost->IsPluginEnabledForType(aContentType.get());
if (rv == NS_ERROR_PLUGIN_DISABLED)
return ePluginDisabled;
if (rv == NS_ERROR_PLUGIN_CLICKTOPLAY)
return ePluginClickToPlay;
if (rv == NS_ERROR_PLUGIN_BLOCKLISTED)
return ePluginBlocklisted;
return ePluginUnsupported;
@ -2046,3 +2042,13 @@ nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
}
return NS_OK;
}
NS_IMETHODIMP
nsObjectLoadingContent::PlayPlugin()
{
if (!nsContentUtils::IsCallerChrome())
return NS_OK;
mShouldPlay = true;
return LoadObject(mURI, true, mContentType, true);
}

View File

@ -66,7 +66,7 @@ enum PluginSupportState {
ePluginOutdated, // The plugin is considered outdated, but not disabled
ePluginOtherState, // Something else (e.g. uninitialized or not a plugin)
ePluginCrashed,
ePluginClickToPlay
ePluginClickToPlay // The plugin is disabled until the user clicks on it
};
/**
@ -410,6 +410,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent
// it may lose the flag.
bool mNetworkCreated : 1;
// Used to keep track of whether or not a plugin should be played.
// This is used for click-to-play plugins.
bool mShouldPlay : 1;
// A specific state that caused us to fallback
PluginSupportState mFallbackReason;

View File

@ -1096,13 +1096,16 @@ WebGLContext::MaybeRestoreContext()
if (mContextLost || mAllowRestore)
return;
bool isEGL = gl->GetContextType() == GLContext::ContextTypeEGL,
isANGLE = gl->IsANGLE();
GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
if (mHasRobustness) {
gl->MakeCurrent();
resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
// This call is safe as it does not actually interact with GL, so the
// context does not have to be current.
} else if (gl->GetContextType() == GLContext::ContextTypeEGL) {
} else if (isEGL) {
// Simulate a ARB_robustness guilty context loss for when we
// get an EGL_CONTEXT_LOST error. It may not actually be guilty,
// but we can't make any distinction, so we must assume the worst
@ -1133,6 +1136,13 @@ WebGLContext::MaybeRestoreContext()
break;
case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
NS_WARNING("WebGL content on the page might have caused the graphics card to reset");
if (isEGL && isANGLE) {
// If we're using ANGLE, we ONLY get back UNKNOWN context resets, including for guilty contexts.
// This means that we can't restore it or risk restoring a guilty context. Should this ever change,
// we can get rid of the whole IsANGLE() junk from GLContext.h since, as of writing, this is the
// only use for it. See ANGLE issue 261.
return;
}
break;
}

View File

@ -4355,9 +4355,18 @@ WebGLContext::CompileShader(nsIWebGLShader *sobj)
if (mEnabledExtensions[WebGL_OES_standard_derivatives])
resources.OES_standard_derivatives = 1;
// notice that on Android, we always use SH_GLSL_OUTPUT, we never use the ESSL backend.
// see bug 709947, the reason is that 1) we dont really need a ESSL backend since the
// source is already ESSL, and 2) we ran into massive Android crashes when we used the ESSL backend.
// But if we wanted to use shader transformations on ES platforms, we would have to use the
// ESSL backend
compiler = ShConstructCompiler((ShShaderType) shader->ShaderType(),
SH_WEBGL_SPEC,
#ifdef MOZ_WIDGET_ANDROID
SH_GLSL_OUTPUT,
#else
gl->IsGLES2() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT,
#endif
&resources);
// We're storing an actual instance of StripComments because, if we don't, the

View File

@ -146,4 +146,8 @@ nsresult
NS_NewDOMCustomEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
nsresult
NS_NewDOMSmsEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
nsresult
NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
nsresult
NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, nsEvent* aEvent);
#endif // nsIPrivateDOMEvent_h__

View File

@ -88,6 +88,34 @@ nsDOMCloseEvent::InitCloseEvent(const nsAString& aType,
return NS_OK;
}
nsresult
nsDOMCloseEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsICloseEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
bool wasClean = false;
PRUint16 code = 0;
nsAutoString reason;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetWasClean(&wasClean);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCode(&code);
NS_ENSURE_SUCCESS(rv, rv);
JSBool found = JS_FALSE;
if (JS_HasProperty(aCx, aObj, "reason", &found) && found) {
rv = eventInit->GetReason(reason);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return InitCloseEvent(aType, bubbles, cancelable, wasClean, code, reason);
}
nsresult
NS_NewDOMCloseEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,

View File

@ -64,6 +64,9 @@ public:
NS_DECL_NSIDOMCLOSEEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsICloseEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
private:
bool mWasClean;
PRUint16 mReasonCode;

View File

@ -78,6 +78,25 @@ nsDOMCustomEvent::InitCustomEvent(const nsAString& aType,
return NS_OK;
}
nsresult
nsDOMCustomEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsICustomEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIVariant> detail;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetDetail(getter_AddRefs(detail));
NS_ENSURE_SUCCESS(rv, rv);
}
return InitCustomEvent(aType, bubbles, cancelable, detail);
}
nsresult
NS_NewDOMCustomEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,

View File

@ -59,6 +59,9 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsICustomEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
private:
nsCOMPtr<nsIVariant> mDetail;
};

View File

@ -61,6 +61,7 @@
#include "nsIScriptError.h"
#include "nsDOMPopStateEvent.h"
#include "mozilla/Preferences.h"
#include "nsJSUtils.h"
using namespace mozilla;
@ -122,7 +123,6 @@ static char *sPopupAllowedEvents;
nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
{
mPresContext = aPresContext;
mPrivateDataDuplicated = false;
if (aEvent) {
@ -159,6 +159,15 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
mEvent->time = PR_Now();
}
InitPresContextData(aPresContext);
NS_ASSERTION(mEvent->message != NS_PAINT, "Trying to create a DOM paint event!");
}
void
nsDOMEvent::InitPresContextData(nsPresContext* aPresContext)
{
mPresContext = aPresContext;
// Get the explicit original target (if it's anonymous make it null)
{
nsCOMPtr<nsIContent> content = GetTargetFromFrame();
@ -168,8 +177,6 @@ nsDOMEvent::nsDOMEvent(nsPresContext* aPresContext, nsEvent* aEvent)
mExplicitOriginalTarget = nsnull;
}
}
NS_ASSERTION(mEvent->message != NS_PAINT, "Trying to create a DOM paint event!");
}
nsDOMEvent::~nsDOMEvent()
@ -190,6 +197,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEvent)
NS_INTERFACE_MAP_ENTRY(nsIDOMEvent)
NS_INTERFACE_MAP_ENTRY(nsIDOMNSEvent)
NS_INTERFACE_MAP_ENTRY(nsIPrivateDOMEvent)
NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Event)
NS_INTERFACE_MAP_END
@ -372,6 +380,67 @@ nsDOMEvent::SetTrusted(bool aTrusted)
return NS_OK;
}
NS_IMETHODIMP
nsDOMEvent::Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
PRUint32 aArgc, jsval* aArgv)
{
NS_ENSURE_TRUE(aArgc >= 1, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
bool trusted = false;
nsCOMPtr<nsPIDOMWindow> w = do_QueryInterface(aOwner);
if (w) {
nsCOMPtr<nsIDocument> d = do_QueryInterface(w->GetExtantDocument());
if (d) {
trusted = nsContentUtils::IsChromeDoc(d);
nsIPresShell* s = d->GetShell();
if (s) {
InitPresContextData(s->GetPresContext());
}
}
}
JSAutoRequest ar(aCx);
JSString* jsstr = JS_ValueToString(aCx, aArgv[0]);
if (!jsstr) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
JS::Anchor<JSString*> deleteProtector(jsstr);
nsDependentJSString type;
NS_ENSURE_STATE(type.init(aCx, jsstr));
nsCOMPtr<nsISupports> dict;
JSObject* obj = nsnull;
if (aArgc >= 2 && !JSVAL_IS_PRIMITIVE(aArgv[1])) {
obj = JSVAL_TO_OBJECT(aArgv[1]);
nsContentUtils::XPConnect()->WrapJS(aCx, obj,
EventInitIID(),
getter_AddRefs(dict));
}
nsresult rv = InitFromCtor(type, dict, aCx, obj);
NS_ENSURE_SUCCESS(rv, rv);
SetTrusted(trusted);
return NS_OK;
}
nsresult
nsDOMEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsIEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
}
return InitEvent(aType, bubbles, cancelable);
}
NS_IMETHODIMP
nsDOMEvent::GetEventPhase(PRUint16* aEventPhase)
{

View File

@ -49,13 +49,17 @@
#include "nsGUIEvent.h"
#include "nsCycleCollectionParticipant.h"
#include "nsAutoPtr.h"
#include "nsIJSNativeInitializer.h"
class nsIContent;
class nsPresContext;
class JSContext;
class JSObject;
class nsDOMEvent : public nsIDOMEvent,
public nsIDOMNSEvent,
public nsIPrivateDOMEvent
public nsIPrivateDOMEvent,
public nsIJSNativeInitializer
{
public:
@ -219,6 +223,16 @@ public:
NS_IMETHOD_(nsEvent*) GetInternalNSEvent();
NS_IMETHOD SetTrusted(bool aTrusted);
// nsIJSNativeInitializer
NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aCx, JSObject* aObj,
PRUint32 aArgc, jsval* aArgv);
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
void InitPresContextData(nsPresContext* aPresContext);
virtual void Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType);
virtual bool Deserialize(const IPC::Message* aMsg, void** aIter);

View File

@ -78,6 +78,34 @@ nsDOMHashChangeEvent::InitHashChangeEvent(const nsAString &aTypeArg,
return NS_OK;
}
nsresult
nsDOMHashChangeEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsIHashChangeEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsAutoString oldURL;
nsAutoString newURL;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
JSBool found = JS_FALSE;
if (JS_HasProperty(aCx, aObj, "oldURL", &found) && found) {
rv = eventInit->GetOldURL(oldURL);
NS_ENSURE_SUCCESS(rv, rv);
}
found = JS_FALSE;
if (JS_HasProperty(aCx, aObj, "newURL", &found) && found) {
rv = eventInit->GetNewURL(newURL);
NS_ENSURE_SUCCESS(rv, rv);
}
}
return InitHashChangeEvent(aType, bubbles, cancelable, oldURL, newURL);
}
nsresult NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,
nsEvent* aEvent)

View File

@ -58,13 +58,12 @@ public:
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIHashChangeEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
protected:
nsString mOldURL;
nsString mNewURL;
};
nsresult NS_NewDOMHashChangeEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,
nsEvent* aEvent);
#endif // nsDOMHashChangeEvent_h__

View File

@ -144,6 +144,61 @@ nsDOMMouseEvent::InitMouseEvent(const nsAString & aType, bool aCanBubble, bool a
return NS_OK;
}
nsresult
nsDOMMouseEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsIMouseEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIDOMWindow> view;
PRInt32 detail = 0;
PRInt32 screenX = 0;
PRInt32 screenY = 0;
PRInt32 clientX = 0;
PRInt32 clientY = 0;
bool ctrl = false;
bool alt = false;
bool shift = false;
bool meta = false;
PRUint16 button = 0;
nsCOMPtr<nsIDOMEventTarget> relatedTarget;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetView(getter_AddRefs(view));
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetDetail(&detail);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetScreenX(&screenX);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetScreenY(&screenY);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetClientX(&clientX);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetClientY(&clientY);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCtrlKey(&ctrl);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetShiftKey(&shift);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetAltKey(&alt);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetMetaKey(&meta);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetButton(&button);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetRelatedTarget(getter_AddRefs(relatedTarget));
NS_ENSURE_SUCCESS(rv, rv);
}
return InitMouseEvent(aType, bubbles, cancelable,
view, detail, screenX, screenY, clientX, clientY,
ctrl, alt, shift, meta,
button, relatedTarget);
}
NS_IMETHODIMP
nsDOMMouseEvent::InitNSMouseEvent(const nsAString & aType, bool aCanBubble, bool aCancelable,
nsIDOMWindow *aView, PRInt32 aDetail, PRInt32 aScreenX,

View File

@ -60,6 +60,9 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMUIEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIMouseEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
protected:
// Specific implementation for a mouse event.
virtual nsresult Which(PRUint32* aWhich);

View File

@ -69,6 +69,25 @@ nsDOMPageTransitionEvent::InitPageTransitionEvent(const nsAString &aTypeArg,
return NS_OK;
}
nsresult
nsDOMPageTransitionEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsIPageTransitionEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
bool persisted = false;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetPersisted(&persisted);
NS_ENSURE_SUCCESS(rv, rv);
}
return InitPageTransitionEvent(aType, bubbles, cancelable, persisted);
}
nsresult NS_NewDOMPageTransitionEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,
nsEvent *aEvent)

View File

@ -55,6 +55,10 @@ public:
// Forward to base class
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIPageTransitionEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
protected:
bool mPersisted;
};

View File

@ -83,6 +83,25 @@ nsDOMPopStateEvent::InitPopStateEvent(const nsAString &aTypeArg,
return NS_OK;
}
nsresult
nsDOMPopStateEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsIPopStateEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIVariant> state;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetState(getter_AddRefs(state));
NS_ENSURE_SUCCESS(rv, rv);
}
return InitPopStateEvent(aType, bubbles, cancelable, state);
}
nsresult NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,
nsEvent* aEvent)

View File

@ -60,12 +60,11 @@ public:
NS_FORWARD_TO_NSDOMEVENT
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIPopStateEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
protected:
nsCOMPtr<nsIVariant> mState;
};
nsresult NS_NewDOMPopStateEvent(nsIDOMEvent** aInstancePtrResult,
nsPresContext* aPresContext,
nsEvent* aEvent);
#endif // nsDOMPopStateEvent_h__

View File

@ -205,6 +205,28 @@ nsDOMUIEvent::InitUIEvent(const nsAString& typeArg,
return NS_OK;
}
nsresult
nsDOMUIEvent::InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj)
{
nsCOMPtr<nsIUIEventInit> eventInit = do_QueryInterface(aDict);
bool bubbles = false;
bool cancelable = false;
nsCOMPtr<nsIDOMWindow> view;
PRInt32 detail = 0;
if (eventInit) {
nsresult rv = eventInit->GetBubbles(&bubbles);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetCancelable(&cancelable);
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetView(getter_AddRefs(view));
NS_ENSURE_SUCCESS(rv, rv);
rv = eventInit->GetDetail(&detail);
NS_ENSURE_SUCCESS(rv, rv);
}
return InitUIEvent(aType, bubbles, cancelable, view, detail);
}
// ---- nsDOMNSUIEvent implementation -------------------
nsIntPoint
nsDOMUIEvent::GetPagePoint()

View File

@ -64,6 +64,9 @@ public:
NS_FORWARD_NSIDOMNSEVENT(nsDOMEvent::)
virtual const nsIID& EventInitIID() { return NS_GET_IID(nsIUIEventInit); }
virtual nsresult InitFromCtor(const nsAString& aType, nsISupports* aDict,
JSContext* aCx, JSObject* aObj);
protected:
// Internal helper functions
nsIntPoint GetClientPoint();

View File

@ -112,6 +112,7 @@ _TEST_FILES = \
empty.js \
test_bug689564.html \
test_bug698929.html \
test_eventctors.html \
$(NULL)
#bug 585630
@ -144,6 +145,7 @@ _CHROME_FILES = \
window_bug617528.xul \
test_bug679494.xul \
file_bug679494.html \
test_eventctors.xul \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,378 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=675884
-->
<head>
<title>Test for Bug 675884</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=675884">Mozilla Bug 675884</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 675884 **/
var receivedEvent;
document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
// Event
var e;
var ex = false;
try {
e = new Event();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new Event("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new Event("hello", { bubbles: true, cancelable: true });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// CustomEvent
try {
e = new CustomEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new CustomEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new CustomEvent("hello", { bubbles: true, cancelable: true, detail: window });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.detail, window , "Wrong event.detail!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new CustomEvent("hello", { cancelable: true, detail: window });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.detail, window , "Wrong event.detail!");
e = new CustomEvent("hello", { detail: 123 });
is(e.detail, 123, "Wrong event.detail!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
var dict = { get detail() { return document.body } };
e = new CustomEvent("hello", dict);
is(e.detail, dict.detail, "Wrong event.detail!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
e = new CustomEvent("hello", 1234);
is(e.detail, null, "Wrong event.detail!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
var dict = { get detail() { throw "foo"; } };
try {
e = new CustomEvent("hello", dict);
} catch (exp) {
ex = true;
}
ok(ex, "Should have thrown an exception!");
ex = false;
// CloseEvent
try {
e = new CloseEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new CloseEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.wasClean, false, "wasClean should be false!");
is(e.code, 0, "code should be 0!");
is(e.reason, "", "reason should be ''!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new CloseEvent("hello",
{ bubbles: true, cancelable: true, wasClean: true, code: 1, reason: "foo" });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.wasClean, true, "wasClean should be true!");
is(e.code, 1, "code should be 1!");
is(e.reason, "foo", "reason should be 'foo'!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new CloseEvent("hello",
{ bubbles: true, cancelable: true, wasClean: true, code: 1 });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.wasClean, true, "wasClean should be true!");
is(e.code, 1, "code should be 1!");
is(e.reason, "", "reason should be ''!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// HashChangeEvent
try {
e = new HashChangeEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new HashChangeEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.oldURL, "", "oldURL should be ''");
is(e.newURL, "", "newURL should be ''");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new HashChangeEvent("hello",
{ bubbles: true, cancelable: true, oldURL: "old", newURL: "new" });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.oldURL, "old", "oldURL should be 'old'");
is(e.newURL, "new", "newURL should be 'new'");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new HashChangeEvent("hello",
{ bubbles: true, cancelable: true, newURL: "new" });
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.oldURL, "", "oldURL should be ''");
is(e.newURL, "new", "newURL should be 'new'");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// PageTransitionEvent
try {
e = new PageTransitionEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new PageTransitionEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.persisted, false, "persisted should be false");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new PageTransitionEvent("hello",
{ bubbles: true, cancelable: true, persisted: true});
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.persisted, true, "persisted should be true");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new PageTransitionEvent("hello", { persisted: true});
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.persisted, true, "persisted should be true");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// PopStateEvent
try {
e = new PopStateEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new PopStateEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.state, null, "persisted should be null");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new PopStateEvent("hello",
{ bubbles: true, cancelable: true, state: window});
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.state, window, "persisted should be window");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new PopStateEvent("hello", { state: window});
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.state, window, "persisted should be window");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// UIEvent
try {
e = new UIEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new UIEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
is(e.detail, 0, "detail should be 0");
is(e.view, null, "view should be null");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
e = new UIEvent("hello",
{ bubbles: true, cancelable: true, view: window, detail: 1});
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(e.bubbles, "Event should bubble!");
ok(e.cancelable, "Event should be cancelable!");
is(e.detail, 1, "detail should be 1");
is(e.view, window, "view should be window");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
// UIEvent
try {
e = new UIEvent();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new MouseEvent("hello");
ok(e.type, "hello", "Wrong event type!");
ok(!e.isTrusted, "Event shouldn't be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
var mouseEventProps =
[ { screenX: 0 },
{ screenY: 0 },
{ clientX: 0 },
{ clientY: 0 },
{ ctrlKey: false },
{ shiftKey: false },
{ altKey: false },
{ metaKey: false },
{ button: 0 },
{ relatedTarget: null }
];
var testProps =
[
{ screenX: 1 },
{ screenY: 2 },
{ clientX: 3 },
{ clientY: 4 },
{ ctrlKey: true },
{ shiftKey: true },
{ altKey: true },
{ metaKey: true },
{ button: 5 },
{ relatedTarget: window }
];
var defaultMouseEventValues = {};
for (var i = 0; i < mouseEventProps.length; ++i) {
for (prop in mouseEventProps[i]) {
ok(prop in e, "MouseEvent doesn't have property " + prop + "!");
defaultMouseEventValues[prop] = mouseEventProps[i][prop];
}
}
while (testProps.length) {
var p = testProps.shift();
e = new MouseEvent("foo", p);
for (var def in defaultMouseEventValues) {
if (!(def in p)) {
is(e[def], defaultMouseEventValues[def], "Wrong default value for " + def + "!");
} else {
is(e[def], p[def], "Wrong event init value for " + def + "!");
}
}
}
SimpleTest.finish();
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,51 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=675884
-->
<window title="Mozilla Bug 675884"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=675884"
target="_blank">Mozilla Bug 675884</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 675884 **/
// Most of the tests are in .html file, but test here that
// isTrusted is handled correctly in chrome.
var receivedEvent;
document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
// Event
var e;
var ex = false;
try {
e = new Event();
} catch(exp) {
ex = true;
}
ok(ex, "First parameter is required!");
ex = false;
e = new Event("hello");
ok(e.type, "hello", "Wrong event type!");
ok(e.isTrusted, "Event should be trusted!");
ok(!e.bubbles, "Event shouldn't bubble!");
ok(!e.cancelable, "Event shouldn't be cancelable!");
document.dispatchEvent(e);
is(receivedEvent, e, "Wrong event!");
SimpleTest.finish();
]]>
</script>
</window>

View File

@ -514,6 +514,7 @@
#include "nsIDOMSmsManager.h"
#include "nsIDOMSmsMessage.h"
#include "nsIDOMSmsEvent.h"
#include "nsIPrivateDOMEvent.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -1574,6 +1575,25 @@ static const nsContractIDMapData kConstructorMap[] =
NS_DEFINE_CONSTRUCTOR_DATA(EventSource, NS_EVENTSOURCE_CONTRACTID)
};
#define NS_DEFINE_EVENT_CTOR(_class) \
nsresult \
NS_DOM##_class##Ctor(nsISupports** aInstancePtrResult) \
{ \
nsIDOMEvent* e = nsnull; \
nsresult rv = NS_NewDOM##_class(&e, nsnull, nsnull); \
*aInstancePtrResult = e; \
return rv; \
}
NS_DEFINE_EVENT_CTOR(Event)
NS_DEFINE_EVENT_CTOR(CustomEvent)
NS_DEFINE_EVENT_CTOR(PopStateEvent)
NS_DEFINE_EVENT_CTOR(HashChangeEvent)
NS_DEFINE_EVENT_CTOR(PageTransitionEvent)
NS_DEFINE_EVENT_CTOR(CloseEvent)
NS_DEFINE_EVENT_CTOR(UIEvent)
NS_DEFINE_EVENT_CTOR(MouseEvent)
struct nsConstructorFuncMapData
{
PRInt32 mDOMClassInfoID;
@ -1583,10 +1603,21 @@ struct nsConstructorFuncMapData
#define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func) \
{ eDOMClassInfo_##_class##_id, _func },
#define NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(_class) \
{ eDOMClassInfo_##_class##_id, NS_DOM##_class##Ctor },
static const nsConstructorFuncMapData kConstructorFuncMap[] =
{
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFileFile::NewFile)
NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(Event)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(CustomEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(PopStateEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(HashChangeEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(PageTransitionEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(CloseEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(UIEvent)
NS_DEFINE_EVENT_CONSTRUCTOR_FUNC_DATA(MouseEvent)
};
nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;

View File

@ -59,3 +59,11 @@ interface nsIDOMCloseEvent : nsIDOMEvent
in unsigned short aReasonCode,
in DOMString aReason);
};
[scriptable, uuid(148ed08e-14f1-4be5-b2f8-23f765738379)]
interface nsICloseEventInit : nsIEventInit
{
attribute boolean wasClean;
attribute unsigned short code;
attribute DOMString reason;
};

View File

@ -49,3 +49,9 @@ interface nsIDOMCustomEvent : nsIDOMEvent
in boolean cancelableArg,
in nsIVariant detailArg);
};
[scriptable, uuid(8c166794-06af-4eac-b76b-bc132e421b06)]
interface nsICustomEventInit : nsIEventInit
{
attribute nsIVariant detail;
};

View File

@ -181,3 +181,10 @@ interface nsIDOMEvent : nsISupports
*/
void stopImmediatePropagation();
};
[scriptable, uuid(fe864f0f-45df-404a-bb27-83c5d08be8d1)]
interface nsIEventInit : nsISupports
{
attribute boolean bubbles;
attribute boolean cancelable;
};

View File

@ -46,3 +46,10 @@ interface nsIDOMHashChangeEvent : nsIDOMEvent
in DOMString oldURLArg,
in DOMString newURLArg);
};
[scriptable, uuid(e56881c1-3714-45bb-bca3-1453ea24ee90)]
interface nsIHashChangeEventInit : nsIEventInit
{
attribute DOMString oldURL;
attribute DOMString newURL;
};

View File

@ -113,3 +113,19 @@ interface nsIDOMMouseEvent : nsIDOMUIEvent
in float pressure,
in unsigned short inputSourceArg);
};
[scriptable, uuid(9495a977-5c9e-4b34-8d51-22bfd9b4fcf6)]
interface nsIMouseEventInit : nsIUIEventInit
{
attribute long screenX;
attribute long screenY;
attribute long clientX;
attribute long clientY;
attribute boolean ctrlKey;
attribute boolean shiftKey;
attribute boolean altKey;
attribute boolean metaKey;
attribute unsigned short button;
// attribute unsigned short buttons; is not supported yet.
attribute nsIDOMEventTarget relatedTarget;
};

View File

@ -60,3 +60,9 @@ interface nsIDOMPageTransitionEvent : nsIDOMEvent
in boolean canCancelArg,
in boolean persisted);
};
[scriptable, uuid(bf3eaa61-5048-48c4-b8b9-9bf833ca63d6)]
interface nsIPageTransitionEventInit : nsIEventInit
{
attribute boolean persisted;
};

View File

@ -49,3 +49,9 @@ interface nsIDOMPopStateEvent : nsIDOMEvent
in boolean cancelableArg,
in nsIVariant stateArg);
};
[scriptable, uuid(2300bd68-f6e0-4c58-a1aa-45f94cdabfbd)]
interface nsIPopStateEventInit : nsIEventInit
{
attribute nsIVariant state;
};

View File

@ -73,3 +73,10 @@ interface nsIDOMUIEvent : nsIDOMEvent
readonly attribute boolean isChar;
};
[scriptable, uuid(610eb27e-9718-4acd-8ed1-7d1840bc6c7f)]
interface nsIUIEventInit : nsIEventInit
{
attribute nsIDOMWindow view;
attribute long detail;
};

View File

@ -46,5 +46,6 @@
#define NS_ERROR_PLUGIN_DISABLED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PLUGINS,1001)
#define NS_ERROR_PLUGIN_BLOCKLISTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PLUGINS,1002)
#define NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PLUGINS,1003)
#define NS_ERROR_PLUGIN_CLICKTOPLAY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_PLUGINS,1004)
#endif // nsPluginError_h__

View File

@ -152,6 +152,7 @@
#include "nsContentErrors.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Preferences.h"
#if defined(XP_WIN)
#include "nsIWindowMediator.h"
@ -1331,10 +1332,18 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType,
nsresult
nsPluginHost::IsPluginEnabledForType(const char* aMimeType)
{
// If plugins.click_to_play is false, plugins should always play
return IsPluginEnabledForType(aMimeType,
!Preferences::GetBool("plugins.click_to_play", false));
}
nsresult
nsPluginHost::IsPluginEnabledForType(const char* aMimeType, bool aShouldPlay)
{
nsPluginTag *plugin = FindPluginForType(aMimeType, true);
if (plugin)
return NS_OK;
return aShouldPlay ? NS_OK : NS_ERROR_PLUGIN_CLICKTOPLAY;
// Pass false as the second arg so we can return NS_ERROR_PLUGIN_DISABLED
// for disabled plug-ins.
@ -1349,7 +1358,7 @@ nsPluginHost::IsPluginEnabledForType(const char* aMimeType)
return NS_ERROR_PLUGIN_DISABLED;
}
return NS_OK;
return aShouldPlay ? NS_OK : NS_ERROR_PLUGIN_CLICKTOPLAY;
}
// check comma delimitered extensions
@ -1377,12 +1386,24 @@ static int CompareExtensions(const char *aExtensionList, const char *aExtension)
return PL_strcasecmp(pExt, aExtension);
}
nsresult
nsPluginHost::IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType)
{
// If plugins.click_to_play is false, plugins should always play
return IsPluginEnabledForExtension(aExtension, aMimeType,
!Preferences::GetBool("plugins.click_to_play", false));
}
nsresult
nsPluginHost::IsPluginEnabledForExtension(const char* aExtension,
const char* &aMimeType)
const char* &aMimeType,
bool aShouldPlay)
{
nsPluginTag *plugin = FindPluginEnabledForExtension(aExtension, aMimeType);
return plugin ? NS_OK : NS_ERROR_FAILURE;
if (plugin)
return aShouldPlay ? NS_OK : NS_ERROR_PLUGIN_CLICKTOPLAY;
return NS_ERROR_FAILURE;
}
class DOMMimeTypeImpl : public nsIDOMMimeType {
@ -2254,11 +2275,6 @@ nsresult nsPluginHost::ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
nsresult nsPluginHost::LoadPlugins()
{
#ifdef ANDROID
if (XRE_GetProcessType() == GeckoProcessType_Content) {
return NS_OK;
}
#endif
// do not do anything if it is already done
// use ReloadPlugins() to enforce loading
if (mPluginsLoaded)

View File

@ -118,7 +118,11 @@ public:
nsIURI *aURL,
nsIPluginInstanceOwner *aOwner);
nsresult IsPluginEnabledForType(const char* aMimeType);
nsresult IsPluginEnabledForType(const char* aMimeType,
bool aShouldPlay);
nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
nsresult IsPluginEnabledForExtension(const char* aExtension, const char* &aMimeType,
bool aShouldPlay);
nsresult GetPluginCount(PRUint32* aPluginCount);
nsresult GetPlugins(PRUint32 aPluginCount, nsIDOMPlugin** aPluginArray);

View File

@ -1695,4 +1695,17 @@ public class GeckoAppShell
public static void sendMessage(String aNumber, String aMessage) {
GeckoSmsManager.send(aNumber, aMessage);
}
public static boolean isTablet() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
Configuration config = GeckoApp.mAppContext.getResources().getConfiguration();
// xlarge is defined by android as screens larger than 960dp x 720dp
// and should include most devices ~7in and up.
// http://developer.android.com/guide/practices/screens_support.html
if ((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE) {
return true;
}
}
return false;
}
}

View File

@ -100,6 +100,7 @@ static const char *sExtensionNames[] = {
"GL_ANGLE_framebuffer_multisample",
"GL_OES_rgb8_rgba8",
"GL_ARB_robustness",
"GL_EXT_robustness",
NULL
};
@ -409,18 +410,32 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
(mSymbols.fMapBuffer && mSymbols.fUnmapBuffer),
"ARB_pixel_buffer_object supported without glMapBuffer/UnmapBuffer being available!");
if (SupportsRobustness() && IsExtensionSupported(ARB_robustness)) {
SymLoadStruct robustnessSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", NULL } },
{ NULL, { NULL } },
};
if (SupportsRobustness()) {
if (IsExtensionSupported(ARB_robustness)) {
SymLoadStruct robustnessSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusARB", NULL } },
{ NULL, { NULL } },
};
if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
NS_RUNTIMEABORT("GL supports ARB_robustness without supplying GetGraphicsResetStatusARB.");
mInitialized = false;
if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
NS_RUNTIMEABORT("GL supports ARB_robustness without supplying GetGraphicsResetStatusARB.");
mInitialized = false;
} else {
mHasRobustness = true;
}
} else if (IsExtensionSupported(EXT_robustness)) {
SymLoadStruct robustnessSymbols[] = {
{ (PRFuncPtr*) &mSymbols.fGetGraphicsResetStatus, { "GetGraphicsResetStatusEXT", NULL } },
{ NULL, { NULL } },
};
if (!LoadSymbols(&robustnessSymbols[0], trygl, prefix)) {
NS_RUNTIMEABORT("GL supports EGL_robustness without supplying GetGraphicsResetStatusEXT.");
mInitialized = false;
} else {
mHasRobustness = true;
}
}
mHasRobustness = true;
}
// Check for aux symbols based on extensions

View File

@ -665,6 +665,14 @@ public:
return mIsGLES2 || IsExtensionSupported(ARB_ES2_compatibility);
}
/**
* Returns true if the context is using ANGLE. This should only be overridden for an ANGLE
* implementation.
*/
virtual bool IsANGLE() {
return false;
}
/**
* The derived class is expected to provide information on whether or not it
* supports robustness.
@ -1270,6 +1278,7 @@ public:
ANGLE_framebuffer_multisample,
OES_rgb8_rgba8,
ARB_robustness,
EXT_robustness,
Extensions_Max
};

View File

@ -215,6 +215,18 @@ static EGLConfig
CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig = nsnull, EGLenum aDepth = 0);
#endif
static EGLint gContextAttribs[] = {
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
LOCAL_EGL_NONE
};
static EGLint gContextAttribsRobustness[] = {
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
//LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT, LOCAL_EGL_TRUE,
LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT, LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT,
LOCAL_EGL_NONE
};
static int
next_power_of_two(int v)
{
@ -245,7 +257,8 @@ static class EGLLibrary
public:
EGLLibrary()
: mInitialized(false),
mEGLLibrary(nsnull)
mEGLLibrary(nsnull),
mHasRobustness(false)
{
mIsANGLE = false;
mHave_EGL_KHR_image_base = false;
@ -429,7 +442,7 @@ public:
return false;
const char *vendor = (const char*) fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
if (vendor && strstr(vendor, "TransGaming") != 0) {
if (vendor && (strstr(vendor, "TransGaming") != 0 || strstr(vendor, "Google Inc.") != 0)) {
mIsANGLE = true;
}
@ -518,6 +531,10 @@ public:
}
}
if (strstr(extensions, "EGL_EXT_create_context_robustness")) {
mHasRobustness = true;
}
mInitialized = true;
reporter.SetSuccessful();
return true;
@ -551,6 +568,10 @@ public:
return mHave_EGL_ANGLE_surface_d3d_texture_2d_share_handle;
}
bool HasRobustness() {
return mHasRobustness;
}
void
DumpEGLConfig(EGLConfig cfg)
{
@ -625,6 +646,7 @@ private:
EGLDisplay mEGLDisplay;
bool mIsANGLE;
bool mHasRobustness;
bool mHave_EGL_KHR_image_base;
bool mHave_EGL_KHR_image_pixmap;
@ -645,22 +667,20 @@ class GLContextEGL : public GLContext
bool aIsOffscreen = false)
{
EGLContext context;
static EGLint cxattribs[] = {
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
LOCAL_EGL_NONE
};
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
shareContext ? shareContext->mContext : EGL_NO_CONTEXT,
cxattribs);
sEGLLibrary.HasRobustness() ? gContextAttribsRobustness
: gContextAttribs);
if (!context) {
if (shareContext) {
shareContext = nsnull;
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
EGL_NO_CONTEXT,
cxattribs);
sEGLLibrary.HasRobustness() ? gContextAttribsRobustness
: gContextAttribs);
if (!context) {
NS_WARNING("Failed to create EGLContext!");
return nsnull;
@ -753,6 +773,7 @@ public:
mIsDoubleBuffered = true;
}
#endif
return ok;
}
@ -766,7 +787,12 @@ public:
bool SupportsRobustness()
{
return false;
return sEGLLibrary.HasRobustness();
}
virtual bool IsANGLE()
{
return sEGLLibrary.IsANGLE();
}
#if defined(MOZ_X11) && defined(MOZ_EGL_XRENDER_COMPOSITE)
@ -2104,16 +2130,12 @@ TRY_ATTRIBS_AGAIN:
sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API);
EGLint cxattrs[] = {
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
LOCAL_EGL_NONE
};
context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
EGL_NO_CONTEXT,
cxattrs);
if (!context) {
sEGLLibrary.HasRobustness() ? gContextAttribsRobustness
: gContextAttribs);
if (!context) {
NS_WARNING("Failed to create context");
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
return nsnull;
@ -2496,15 +2518,11 @@ GLContextEGL::CreateBasicEGLPixmapOffscreenContext(const gfxIntSize& aSize,
return nsnull;
}
EGLint cxattribs[] = {
LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
LOCAL_EGL_NONE
};
EGLContext context = sEGLLibrary.fCreateContext(EGL_DISPLAY(),
config,
EGL_NO_CONTEXT,
cxattribs);
sEGLLibrary.HasRobustness() ? gContextAttribsRobustness
: gContextAttribs);
if (!context) {
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
return nsnull;

View File

@ -3059,6 +3059,10 @@ typedef ptrdiff_t GLintptr;
#define LOCAL_WGL_NO_RESET_NOTIFICATION_ARB 0x8261
#define LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
#define LOCAL_EGL_NO_RESET_NOTIFICATION_EXT 0x31BE
#define LOCAL_EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF
#define LOCAL_GL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define LOCAL_GL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define LOCAL_GL_CONTEXT_LAYER_PLANE_ARB 0x2093
@ -3071,6 +3075,8 @@ typedef ptrdiff_t GLintptr;
#define LOCAL_WGL_CONTEXT_FLAGS_ARB 0x2094
#define LOCAL_WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT 0x30BF
#define LOCAL_GL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define LOCAL_GL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002

View File

@ -147,7 +147,7 @@ NS_IMETHODIMP nsPNGEncoder::StartImageEncode(PRUint32 aWidth,
mPNG = png_create_write_struct(PNG_LIBPNG_VER_STRING,
nsnull,
ErrorCallback,
ErrorCallback);
WarningCallback);
if (! mPNG)
return NS_ERROR_OUT_OF_MEMORY;
@ -665,10 +665,10 @@ nsPNGEncoder::StripAlpha(const PRUint8* aSrc, PRUint8* aDest,
}
// nsPNGEncoder::ErrorCallback
// nsPNGEncoder::WarningCallback
void // static
nsPNGEncoder::ErrorCallback(png_structp png_ptr,
nsPNGEncoder::WarningCallback(png_structp png_ptr,
png_const_charp warning_msg)
{
#ifdef DEBUG
@ -679,6 +679,25 @@ nsPNGEncoder::ErrorCallback(png_structp png_ptr,
}
// nsPNGEncoder::ErrorCallback
void // static
nsPNGEncoder::ErrorCallback(png_structp png_ptr,
png_const_charp error_msg)
{
#ifdef DEBUG
// XXX: these messages are probably useful callers...
// use nsIConsoleService?
PR_fprintf(PR_STDERR, "PNG Encoder: %s\n", error_msg);;
#endif
#if PNG_LIBPNG_VER < 10500
longjmp(png_ptr->jmpbuf, 1);
#else
png_longjmp(png_ptr, 1);
#endif
}
// nsPNGEncoder::WriteCallback
void // static

View File

@ -81,7 +81,8 @@ protected:
PRUint32 aPixelWidth, bool aUseTransparency);
void StripAlpha(const PRUint8* aSrc, PRUint8* aDest,
PRUint32 aPixelWidth);
static void ErrorCallback(png_structp png_ptr, png_const_charp warning_msg);
static void WarningCallback(png_structp png_ptr, png_const_charp warning_msg);
static void ErrorCallback(png_structp png_ptr, png_const_charp error_msg);
static void WriteCallback(png_structp png, png_bytep data, png_size_t size);
void NotifyListener();

View File

@ -893,7 +893,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
clazz->name, si->GetJSClass()->name);
} else if (clazz == &js::FunctionClass) {
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj);
JSFunction* fun = JS_GetObjectFunction(obj);
JSString* str = JS_GetFunctionId(fun);
if (str) {
NS_ConvertUTF16toUTF8 fname(JS_GetInternedStringChars(str));
@ -920,15 +920,8 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
JS_snprintf(name, sizeof(name), "JS %s", trace_types[traceKind]);
}
if(traceKind == JSTRACE_OBJECT) {
JSObject *global = JS_GetGlobalForObject(NULL, static_cast<JSObject*>(p));
char fullname[100];
JS_snprintf(fullname, sizeof(fullname),
"%s (global=%p)", name, global);
cb.DescribeGCedNode(isMarked, sizeof(JSObject), fullname);
} else {
cb.DescribeGCedNode(isMarked, sizeof(JSObject), name);
}
// Disable printing global for objects while we figure out ObjShrink fallout.
cb.DescribeGCedNode(isMarked, sizeof(JSObject), name);
} else {
cb.DescribeGCedNode(isMarked, sizeof(JSObject), "JS Object");
}

View File

@ -75,6 +75,8 @@ _CHROME_FILES = \
test_getweakmapkeys.xul \
test_weakmaps.xul \
test_bug706301.xul \
test_ccbeginfail.xul \
test_ccdump.xul \
$(NULL)
# Disabled until this test gets updated to test the new proxy based

View File

@ -0,0 +1,67 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=710761
-->
<window title="Mozilla Bug 710761"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=710761"
target="_blank">Mozilla Bug 710761</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 710761 **/
let noCallbacks = true;
var beginFailListener = {
QueryInterface: function QueryInterface(aIID) {
if (aIID.equals(Components.interfaces.nsICycleCollectorListener) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
/* nsICycleCollectorListener */
begin: function () {
throw Components.results.NS_ERROR_FAILURE;
},
noteRefCountedObject: function (addr, rc, descr) {
noCallbacks = false;
},
noteGCedObject: function (addr, marked, descr) {
noCallbacks = false;
},
noteEdge: function (addr, descr) {
noCallbacks = false;
},
beginResults: function () {
noCallbacks = false;
},
describeRoot: function (addr, known) {
noCallbacks = false;
},
describeGarbage: function (addr) {
noCallbacks = false;
},
end: function () {
noCallbacks = false;
},
};
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.cycleCollect(beginFailListener);
ok(noCallbacks, "If cycle collector listener begin fails, no further callbacks should be called.");
]]>
</script>
</window>

View File

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=709162
-->
<window title="Mozilla Bug 709162"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=709162"
target="_blank">Mozilla Bug 709162</a>
</body>
<!-- test code goes here -->
<script type="application/javascript">
<![CDATA[
/** Test for Bug 709162 **/
var emptyListener = {
QueryInterface: function QueryInterface(aIID) {
if (aIID.equals(Components.interfaces.nsICycleCollectorListener) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
/* nsICycleCollectorListener */
begin: function () {},
noteRefCountedObject: function (addr, rc, descr) {},
noteGCedObject: function (addr, marked, descr) {},
noteEdge: function (addr, descr) {},
beginResults: function () {},
describeRoot: function (addr, known) {},
describeGarbage: function (addr) {},
end: function () {},
};
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.cycleCollect(emptyListener);
ok(true, "Dump cycle collector graph without crashing.");
]]>
</script>
</window>

View File

@ -0,0 +1,154 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Margaret Leibovic <margaret.leibovic@gmail.com>
* Sriram Ramasubramanian <sriram@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.gecko;
import org.mozilla.gecko.gfx.FloatSize;
import android.content.Context;
import android.util.Log;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.ListView;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
public class AutoCompletePopup extends ListView {
private Context mContext;
private RelativeLayout.LayoutParams mLayout;
private int mWidth;
private int mHeight;
private Animation mAnimation;
private static final String LOGTAG = "AutoCompletePopup";
public AutoCompletePopup(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mAnimation = AnimationUtils.loadAnimation(context, R.anim.grow_fade_in);
mAnimation.setDuration(75);
setFocusable(false);
setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parentView, View view, int position, long id) {
String value = ((TextView) view).getText().toString();
GeckoAppShell.sendEventToGecko(new GeckoEvent("FormAssist:AutoComplete", value));
hide();
}
});
}
public void show(JSONArray suggestions, JSONArray rect, double zoom) {
ArrayAdapter<String> adapter = new ArrayAdapter<String>(mContext, R.layout.autocomplete_list_item);
for (int i = 0; i < suggestions.length(); i++) {
try {
adapter.add(suggestions.get(i).toString());
} catch (JSONException e) {
Log.i(LOGTAG, "JSONException: " + e);
}
}
setAdapter(adapter);
if (isShown())
return;
setVisibility(View.VISIBLE);
startAnimation(mAnimation);
if (mLayout == null) {
mLayout = (RelativeLayout.LayoutParams) getLayoutParams();
mWidth = mLayout.width;
mHeight = mLayout.height;
}
int left = 0;
int top = 0;
int width = 0;
int height = 0;
try {
left = (int) (rect.getDouble(0) * zoom);
top = (int) (rect.getDouble(1) * zoom);
width = (int) (rect.getDouble(2) * zoom);
height = (int) (rect.getDouble(3) * zoom);
} catch (JSONException e) { }
int listWidth = mWidth;
int listHeight = mHeight;
int listLeft = left < 0 ? 0 : left;
int listTop = top + height;
FloatSize viewport = GeckoApp.mAppContext.getLayerController().getViewportSize();
// If the textbox is smaller than the screen-width,
// shrink the list's width
if ((left + width) < viewport.width)
listWidth = left + width;
// If the list is extending outside of the viewport
// try moving above
if (((listTop + listHeight) > viewport.height) && (listHeight <= top))
listTop = (top - listHeight);
mLayout = new RelativeLayout.LayoutParams(listWidth, listHeight);
mLayout.setMargins(listLeft, listTop, 0, 0);
setLayoutParams(mLayout);
requestLayout();
}
public void hide() {
if (isShown()) {
setVisibility(View.GONE);
GeckoAppShell.sendEventToGecko(new GeckoEvent("FormAssist:Closed", null));
}
}
}

View File

@ -121,6 +121,7 @@ abstract public class GeckoApp
public static BrowserToolbar mBrowserToolbar;
public static DoorHangerPopup mDoorHangerPopup;
public static AutoCompletePopup mAutoCompletePopup;
public Favicons mFavicons;
private Geocoder mGeocoder;
@ -925,6 +926,23 @@ abstract public class GeckoApp
mBrowserToolbar.setVisibility(View.VISIBLE);
}
});
} else if (event.equals("FormAssist:AutoComplete")) {
final JSONArray suggestions = message.getJSONArray("suggestions");
if (suggestions.length() == 0) {
mMainHandler.post(new Runnable() {
public void run() {
mAutoCompletePopup.hide();
}
});
} else {
final JSONArray rect = message.getJSONArray("rect");
final double zoom = message.getDouble("zoom");
mMainHandler.post(new Runnable() {
public void run() {
mAutoCompletePopup.show(suggestions, rect, zoom);
}
});
}
} else if (event.equals("AgentMode:Changed")) {
Tab.AgentMode agentMode = message.getString("agentMode").equals("mobile") ? Tab.AgentMode.MOBILE : Tab.AgentMode.DESKTOP;
int tabId = message.getInt("tabId");
@ -958,6 +976,7 @@ abstract public class GeckoApp
}
public void run() {
mAutoCompletePopup.hide();
if (mAboutHomeContent == null) {
mAboutHomeContent = (AboutHomeContent) findViewById(R.id.abouthome_content);
mAboutHomeContent.init(GeckoApp.mAppContext);
@ -1059,6 +1078,7 @@ abstract public class GeckoApp
mMainHandler.post(new Runnable() {
public void run() {
mAutoCompletePopup.hide();
if (Tabs.getInstance().isSelectedTab(tab)) {
mBrowserToolbar.setTitle(tab.getDisplayTitle());
mBrowserToolbar.setFavicon(tab.getFavicon());
@ -1324,6 +1344,7 @@ abstract public class GeckoApp
mMainLayout = (LinearLayout) findViewById(R.id.main_layout);
mDoorHangerPopup = new DoorHangerPopup(this);
mAutoCompletePopup = (AutoCompletePopup) findViewById(R.id.autocomplete_popup);
Tabs tabs = Tabs.getInstance();
Tab tab = tabs.getSelectedTab();
@ -1415,6 +1436,7 @@ abstract public class GeckoApp
GeckoAppShell.registerGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
GeckoAppShell.registerGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
mConnectivityFilter = new IntentFilter();
mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
@ -1643,6 +1665,7 @@ abstract public class GeckoApp
GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Hide", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("ToggleChrome:Show", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("AgentMode:Changed", GeckoApp.mAppContext);
GeckoAppShell.unregisterGeckoEventListener("FormAssist:AutoComplete", GeckoApp.mAppContext);
mFavicons.close();
@ -1666,7 +1689,10 @@ abstract public class GeckoApp
public void onConfigurationChanged(android.content.res.Configuration newConfig)
{
Log.i(LOGTAG, "configuration changed");
// nothing, just ignore
// hide the autocomplete list on rotation
mAutoCompletePopup.hide();
super.onConfigurationChanged(newConfig);
}

View File

@ -1550,6 +1550,19 @@ public class GeckoAppShell
GeckoSmsManager.send(aNumber, aMessage);
}
public static boolean isTablet() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
Configuration config = GeckoApp.mAppContext.getResources().getConfiguration();
// xlarge is defined by android as screens larger than 960dp x 720dp
// and should include most devices ~7in and up.
// http://developer.android.com/guide/practices/screens_support.html
if ((config.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE) {
return true;
}
}
return false;
}
public static void emitGeckoAccessibilityEvent (int eventType, String role, String text, String description, boolean enabled, boolean checked, boolean password) {
AccessibilityManager accessibilityManager =
(AccessibilityManager) GeckoApp.mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE);

View File

@ -196,6 +196,9 @@ public class GeckoPreferences
// send the Preferences:Set message to Gecko
public static void setPreference(String pref, Object value) {
if (pref == null || pref.length() == 0)
return;
try {
JSONObject jsonPref = new JSONObject();
jsonPref.put("name", pref);

View File

@ -50,6 +50,7 @@ DIST_FILES = package-name.txt
JAVAFILES = \
AboutHomeContent.java \
AlertNotification.java \
AutoCompletePopup.java \
AwesomeBar.java \
AwesomeBarTabs.java \
BrowserToolbar.java \
@ -174,6 +175,7 @@ DEFINES += -DMOZ_ANDROID_SHARED_ID="$(ANDROID_PACKAGE_NAME).sharedID"
endif
RES_LAYOUT = \
res/layout/autocomplete_list_item.xml \
res/layout/awesomebar_header_row.xml \
res/layout/awesomebar_row.xml \
res/layout/awesomebar_search.xml \
@ -369,6 +371,7 @@ MOZ_ANDROID_DRAWABLES += mobile/android/base/resources/drawable/abouthome_bg.png
mobile/android/base/resources/drawable/address_bar_bg.xml \
mobile/android/base/resources/drawable/address_bar_url_default.xml \
mobile/android/base/resources/drawable/address_bar_url_pressed.xml \
mobile/android/base/resources/drawable/autocomplete_list_bg.9.png \
mobile/android/base/resources/drawable/awesomebar_tab_focus.xml \
mobile/android/base/resources/drawable/awesomebar_tab_focus_selected.xml \
mobile/android/base/resources/drawable/awesomebar_tab_indicator.xml \

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

View File

@ -24,6 +24,15 @@
</org.mozilla.gecko.AboutHomeContent>
<org.mozilla.gecko.AutoCompletePopup android:id="@+id/autocomplete_popup"
style="@android:style/Widget.ListView.White"
android:layout_width="fill_parent"
android:layout_height="100dip"
android:background="@drawable/autocomplete_list_bg"
android:cacheColorHint="#ffffff"
android:listSelector="@android:drawable/list_selector_background"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
android:textColor="?android:attr/textColorPrimaryInverse"
android:layout_gravity="center_vertical"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="3dp"
android:paddingBottom="3dp"/>

View File

@ -31,6 +31,15 @@
</org.mozilla.gecko.AboutHomeContent>
<org.mozilla.gecko.AutoCompletePopup android:id="@+id/autocomplete_popup"
style="@android:style/Widget.ListView.White"
android:layout_width="fill_parent"
android:layout_height="100dip"
android:background="@drawable/autocomplete_list_bg"
android:cacheColorHint="#ffffff"
android:listSelector="@android:drawable/list_selector_background"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>

View File

@ -311,12 +311,14 @@ public class PanZoomController
cancelTouch();
// fall through
case PANNING_HOLD_LOCKED:
GeckoApp.mAppContext.mAutoCompletePopup.hide();
mState = PanZoomState.PANNING_LOCKED;
// fall through
case PANNING_LOCKED:
track(event);
return true;
case PANNING_HOLD:
GeckoApp.mAppContext.mAutoCompletePopup.hide();
mState = PanZoomState.PANNING;
// fall through
case PANNING:
@ -779,10 +781,11 @@ public class PanZoomController
// If we aren't overscrolled, just apply friction.
float excess = getExcess();
if (disableSnap || FloatUtils.fuzzyEquals(excess, 0.0f)) {
float absvelocity = (float)
Math.pow(Math.pow(velocity, FRICTION_FACTOR) * FRICTION,
float absvelocity = Math.abs(velocity);
absvelocity = (float)Math.pow(Math.pow(absvelocity, FRICTION_FACTOR) * FRICTION,
1 / FRICTION_FACTOR);
velocity = Math.copySign(absvelocity, velocity);
// Math.copySign doesn't exist on Android 2.2
velocity = (velocity < 0 ? -absvelocity : absvelocity);
if (Math.abs(velocity) < 0.1f) {
velocity = 0.0f;
@ -990,6 +993,8 @@ public class PanZoomController
throw new RuntimeException(ex);
}
GeckoApp.mAppContext.mAutoCompletePopup.hide();
GeckoEvent e = new GeckoEvent("Gesture:SingleTap", ret.toString());
GeckoAppShell.sendEventToGecko(e);
return true;

View File

@ -201,6 +201,7 @@ var BrowserApp = {
NativeWindow.init();
Downloads.init();
FormAssistant.init();
OfflineApps.init();
IndexedDB.init();
XPInstallObserver.init();
@ -209,6 +210,8 @@ var BrowserApp = {
// Init LoginManager
Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
// Init FormHistory
Cc["@mozilla.org/satchel/form-history;1"].getService(Ci.nsIFormHistory2);
let uri = "about:home";
if ("arguments" in window && window.arguments[0])
@ -262,6 +265,7 @@ var BrowserApp = {
shutdown: function shutdown() {
NativeWindow.uninit();
FormAssistant.uninit();
OfflineApps.uninit();
IndexedDB.uninit();
ViewportHandler.uninit();
@ -1393,8 +1397,12 @@ Tab.prototype = {
let browser = BrowserApp.getBrowserForWindow(contentWin);
let uri = browser.currentURI.spec;
let documentURI = browser.contentDocument.documentURIObject.spec;
let contentType = browser.contentDocument.contentType;
let documentURI = "";
let contentType = "";
if (browser.contentDocument) {
documentURI = browser.contentDocument.documentURIObject.spec;
contentType = browser.contentDocument.contentType;
}
let message = {
gecko: {
@ -2172,8 +2180,99 @@ var ErrorPageEventHandler = {
}
};
var FormAssistant = {
// Used to keep track of the element that corresponds to the current
// autocomplete suggestions
_currentInputElement: null,
init: function() {
Services.obs.addObserver(this, "FormAssist:AutoComplete", false);
Services.obs.addObserver(this, "FormAssist:Closed", false);
BrowserApp.deck.addEventListener("compositionstart", this, false);
BrowserApp.deck.addEventListener("compositionupdate", this, false);
},
uninit: function() {
Services.obs.removeObserver(this, "FormAssist:AutoComplete");
Services.obs.removeObserver(this, "FormAssist:Closed");
},
observe: function(aSubject, aTopic, aData) {
switch (aTopic) {
case "FormAssist:AutoComplete":
if (!this._currentInputElement)
break;
// Remove focus from the textbox to avoid some bad IME interactions
this._currentInputElement.blur();
this._currentInputElement.value = aData;
break;
case "FormAssist:Closed":
this._currentInputElement = null;
break;
}
},
handleEvent: function(aEvent) {
switch (aEvent.type) {
case "compositionstart":
case "compositionupdate":
let currentElement = aEvent.target;
if (!this._isAutocomplete(currentElement))
break;
// Keep track of input element so we can fill it in if the user
// selects an autocomplete suggestion
this._currentInputElement = currentElement;
let suggestions = this._getAutocompleteSuggestions(aEvent.data, currentElement);
let rect = currentElement.getBoundingClientRect();
let zoom = BrowserApp.selectedTab.viewport.zoom;
sendMessageToJava({
gecko: {
type: "FormAssist:AutoComplete",
suggestions: suggestions,
rect: [rect.left, rect.top, rect.width, rect.height],
zoom: zoom
}
});
}
},
_isAutocomplete: function (aElement) {
if (!(aElement instanceof HTMLInputElement) ||
(aElement.getAttribute("type") == "password") ||
(aElement.hasAttribute("autocomplete") &&
aElement.getAttribute("autocomplete").toLowerCase() == "off"))
return false;
return true;
},
/** Retrieve the autocomplete list from the autocomplete service for an element */
_getAutocompleteSuggestions: function(aSearchString, aElement) {
let results = Cc["@mozilla.org/satchel/form-autocomplete;1"].
getService(Ci.nsIFormAutoComplete).
autoCompleteSearch(aElement.name || aElement.id, aSearchString, aElement, null);
let suggestions = [];
if (results.matchCount > 0) {
for (let i = 0; i < results.matchCount; i++) {
let value = results.getValueAt(i);
// Do not show the value if it is the current one in the input field
if (value == aSearchString)
continue;
suggestions.push(value);
}
}
return suggestions;
},
show: function(aList, aElement) {
let data = JSON.parse(sendMessageToJava({ gecko: aList }));
let selected = data.button;

View File

@ -55,7 +55,7 @@ let modules = {
privileged: true,
hide: true
},
get firefox() this[fennec],
get firefox() this.fennec,
// about:blank has some bad loading behavior we can avoid, if we use an alias
empty: {

View File

@ -177,15 +177,21 @@ let Util = {
return this._isTablet = true;
#ifdef ANDROID
// Disable tablet mode on non-honeycomb devices because of theme bugs (bug 705026)
let sysInfo = Cc["@mozilla.org/system-info;1"].getService(Ci.nsIPropertyBag2);
let shellVersion = sysInfo.get("shellVersion") || "";
let matches = shellVersion.match(/\((\d+)\)$/);
if (matches) {
let sdkVersion = parseInt(matches[1]);
if (sdkVersion < 11 || sdkVersion > 13)
// Disable tablet mode on pre-honeycomb devices because of theme bugs (bug 705026)
if (sdkVersion < 11)
return this._isTablet = false;
// Always enable tablet mode on honeycomb devices.
if (sdkVersion < 14)
return this._isTablet = true;
}
// On Ice Cream Sandwich devices, switch modes based on screen size.
return this._isTablet = sysInfo.get("isTablet");
#endif
let dpi = this.displayDPI;

View File

@ -146,7 +146,7 @@ chrome.jar:
skin/images/aurora-lightbox-close.png (images/aurora-lightbox-close.png)
chrome.jar:
% skin browser classic/1.0 %skin/gingerbread/ os=Android osversion=2.3 osversion=2.3.3 osversion=2.3.4 osversion=2.3.5 osversion=2.3.6 osversion=2.3.7 osversion=2.3.8 osversion>=4.0
% skin browser classic/1.0 %skin/gingerbread/ os=Android osversion>=2.3
% skin browser gingerbread/1.0 %skin/gingerbread/
skin/gingerbread/aboutPage.css (aboutPage.css)
skin/gingerbread/about.css (about.css)
@ -285,7 +285,10 @@ chrome.jar:
skin/gingerbread/images/aurora-lightbox-close.png (images/aurora-lightbox-close.png)
chrome.jar:
% skin browser classic/1.0 %skin/honeycomb/ os=Android osversion=3.0 osversion=3.1 osversion=3.2 osversion=3.2.1 osversion=3.2.2 osversion=3.2.3 osversion=3.2.4 osversion=3.2.5 osversion=3.2.6 osversion=3.2.7 osversion=3.2.8 osversion=3.2.9
# Always use the honeycomb theme on honeycomb devices.
% skin browser classic/1.0 %skin/honeycomb/ os=Android osversion>=3.0
# On Ice Cream Sandwich devices, switch themes based on screen size.
% skin browser classic/1.0 %skin/gingerbread/ os=Android osversion>=4.0 tablet=0
% skin browser honeycomb/1.0 %skin/honeycomb/
skin/honeycomb/aboutPage.css (aboutPage.css)
skin/honeycomb/about.css (about.css)

View File

@ -1472,6 +1472,9 @@ pref("dom.max_script_run_time", 10);
// resolved.
pref("hangmonitor.timeout", 0);
// If true, plugins will be click to play
pref("plugins.click_to_play", false);
#ifndef DEBUG
// How long a plugin is allowed to process a synchronous IPC message
// before we consider it "hung".

View File

@ -1 +1 @@
http://hg.mozilla.org/projects/addon-sdk/archive/52fd4dc4e77d.tar.bz2
http://hg.mozilla.org/projects/addon-sdk/archive/34b9f7aff342.tar.bz2

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Taras Glek <tglek@mozilla.com>
* Vladan Djeric <vdjeric@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -81,7 +82,7 @@ public:
typedef nsBaseHashtableET<nsCStringHashKey, StmtStats> SlowSQLEntryType;
private:
bool AddSlowSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread);
bool AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread);
// This is used for speedy JS string->Telemetry::ID conversions
typedef nsBaseHashtableET<nsCharPtrHashKey, Telemetry::ID> CharPtrEntryType;
@ -325,41 +326,26 @@ TelemetryImpl::NewHistogram(const nsACString &name, PRUint32 min, PRUint32 max,
struct EnumeratorArgs {
JSContext *cx;
JSObject *statsObj;
JSObject *statementsObj;
int32 statementIndex;
};
PLDHashOperator
StatementEnumerator(TelemetryImpl::SlowSQLEntryType *entry, void *arg)
{
EnumeratorArgs *args = static_cast<EnumeratorArgs *>(arg);
const nsACString &statement = entry->GetKey();
const nsACString &sql = entry->GetKey();
jsval hitCount = UINT_TO_JSVAL(entry->mData.hitCount);
jsval totalTime = UINT_TO_JSVAL(entry->mData.totalTime);
args->statementIndex++;
JSObject *hitsAndTimeObj = JS_NewArrayObject(args->cx, 2, nsnull);
if (!hitsAndTimeObj ||
!JS_SetElement(args->cx, hitsAndTimeObj, 0, &hitCount) ||
!JS_SetElement(args->cx, hitsAndTimeObj, 1, &totalTime))
JSObject *arrayObj = JS_NewArrayObject(args->cx, 2, nsnull);
if (!arrayObj ||
!JS_SetElement(args->cx, arrayObj, 0, &hitCount) ||
!JS_SetElement(args->cx, arrayObj, 1, &totalTime))
return PL_DHASH_STOP;
jsid propertyId = INT_TO_JSID(args->statementIndex);
JSBool success = JS_DefinePropertyById(args->cx, args->statsObj,
INT_TO_JSID(args->statementIndex),
OBJECT_TO_JSVAL(hitsAndTimeObj),
NULL, NULL, JSPROP_ENUMERATE);
if (!success)
return PL_DHASH_STOP;
JSString *string = JS_NewStringCopyN(args->cx, statement.BeginReading(), statement.Length());
if (!string)
return PL_DHASH_STOP;
success = JS_DefinePropertyById(args->cx, args->statementsObj,
INT_TO_JSID(args->statementIndex),
STRING_TO_JSVAL(string), NULL, NULL,
JSPROP_ENUMERATE);
JSBool success = JS_DefineProperty(args->cx, args->statsObj,
sql.BeginReading(),
OBJECT_TO_JSVAL(arrayObj),
NULL, NULL, JSPROP_ENUMERATE);
if (!success)
return PL_DHASH_STOP;
@ -367,28 +353,20 @@ StatementEnumerator(TelemetryImpl::SlowSQLEntryType *entry, void *arg)
}
bool
TelemetryImpl::AddSlowSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread)
TelemetryImpl::AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread)
{
JSObject *statementsObj = JS_NewObject(cx, NULL, NULL, NULL);
JSObject *statsObj = JS_NewObject(cx, NULL, NULL, NULL);
if (!statementsObj || !statsObj)
if (!statsObj)
return false;
JSBool ok = JS_DefineProperty(cx, rootObj,
mainThread ? "slowSQLOnMain" : "slowSQLOnOther",
OBJECT_TO_JSVAL(statementsObj),
mainThread ? "mainThread" : "otherThreads",
OBJECT_TO_JSVAL(statsObj),
NULL, NULL, JSPROP_ENUMERATE);
if (!ok)
return false;
ok = JS_DefineProperty(cx, rootObj,
mainThread ? "slowSQLStatsMain" : "slowSQLStatsOther",
OBJECT_TO_JSVAL(statsObj),
NULL, NULL, JSPROP_ENUMERATE);
if (!ok)
return false;
EnumeratorArgs args = { cx, statsObj, statementsObj, 0 };
EnumeratorArgs args = { cx, statsObj };
nsTHashtable<SlowSQLEntryType> *sqlMap;
sqlMap = (mainThread ? &mSlowSQLOnMainThread : &mSlowSQLOnOtherThread);
PRUint32 num = sqlMap->EnumerateEntries(StatementEnumerator,
@ -420,13 +398,23 @@ TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret)
return NS_ERROR_FAILURE;
}
}
return NS_OK;
}
NS_IMETHODIMP
TelemetryImpl::GetSlowSQL(JSContext *cx, jsval *ret)
{
JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL);
if (!root_obj)
return NS_ERROR_FAILURE;
*ret = OBJECT_TO_JSVAL(root_obj);
MutexAutoLock hashMutex(mHashMutex);
// Add info about slow SQL queries on the main thread
if (!AddSlowSQLInfo(cx, root_obj, true))
if (!AddSQLInfo(cx, root_obj, true))
return NS_ERROR_FAILURE;
// Add info about slow SQL queries on other threads
if (!AddSlowSQLInfo(cx, root_obj, false))
if (!AddSQLInfo(cx, root_obj, false))
return NS_ERROR_FAILURE;
return NS_OK;

View File

@ -18,6 +18,7 @@
*
* Contributor(s):
* Taras Glek <tglek@mozilla.com>
* Vladan Djeric <vdjeric@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -323,7 +324,8 @@ TelemetryPing.prototype = {
ver: PAYLOAD_VERSION,
info: this.getMetadata(reason),
simpleMeasurements: getSimpleMeasurements(),
histograms: this.getHistograms()
histograms: this.getHistograms(),
slowSQL: Telemetry.slowSQL
};
let isTestPing = (reason == "test-ping");

View File

@ -21,6 +21,7 @@
*
* Contributor(s):
* Taras Glek <tglek@mozilla.com>
* Vladan Djeric <vdjeric@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -66,6 +67,24 @@ interface nsITelemetry : nsISupports
[implicit_jscontext]
readonly attribute jsval histogramSnapshots;
/*
* An object containing information about slow SQL prepared statements.
*
* {
* mainThread: { "sqlString1": [<hit count>, <total time>], "sqlString2": [...], ... },
* otherThreads: { "sqlString3": [<hit count>, <total time>], "sqlString4": [...], ... }
* }
*
* where:
* mainThread: Slow statements that executed on the main thread
* otherThreads: Slow statements that executed on a non-main thread
* sqlString - String of the offending prepared statement
* hit count - The number of times this statement required longer than the threshold time to execute
* total time - The sum of all execution times above the threshold time for this statement
*/
[implicit_jscontext]
readonly attribute jsval slowSQL;
/**
* Create and return a histogram where bucket sizes increase exponentially. Parameters:
*

View File

@ -90,6 +90,9 @@ function checkHistograms(request, response) {
let tc = payload.histograms[TELEMETRY_SUCCESS]
do_check_eq(uneval(tc),
uneval(expected_tc));
do_check_true(("mainThread" in payload.slowSQL) &&
("otherThreads" in payload.slowSQL));
gFinished = true;
}

View File

@ -91,6 +91,11 @@ function test_getHistogramById() {
do_check_true(s.static);
}
function test_getSlowSQL() {
var slow = Telemetry.slowSQL;
do_check_true(("mainThread" in slow) && ("otherThreads" in slow));
}
// Check that telemetry doesn't record in private mode
function test_privateMode() {
var h = Telemetry.newHistogram("test::private_mode_boolean", 1,2,3, Telemetry.HISTOGRAM_BOOLEAN);
@ -117,5 +122,6 @@ function run_test()
test_boolean_histogram();
test_getHistogramById();
test_getSlowSQL();
test_privateMode();
}

View File

@ -51,6 +51,8 @@ MODULE = test_extensionmanager
ifneq (mobile,$(MOZ_BUILD_APP))
DIRS += \
xpinstall \
browser \
mochitest \
$(NULL)
endif

View File

@ -7,7 +7,6 @@
const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul";
const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url";
const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion";
@ -35,10 +34,6 @@ function test() {
run_next_test();
}
registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_GETADDONS_CACHE_ENABLED);
});
function end_test() {
// Test generates a lot of available installs so just cancel them all
AddonManager.getAllInstalls(function(aInstalls) {

View File

@ -27,8 +27,6 @@ function test() {
}
function end_test() {
Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
// Test generates a lot of available installs so just cancel them all
AddonManager.getAllInstalls(function(aInstalls) {
aInstalls.forEach(function(aInstall) {

View File

@ -73,7 +73,6 @@ function test() {
function end_test() {
Services.prefs.clearUserPref(PREF_GETADDONS_GETSEARCHRESULTS);
close_manager(gManagerWindow, finish);
}

View File

@ -4,7 +4,6 @@
// Tests that the discovery view loads properly
const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html";
var gManagerWindow;
@ -40,10 +39,6 @@ function test() {
// Temporarily enable caching
Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
registerCleanupFunction(function() {
Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false);
});
waitForExplicitFinish();
gProvider = new MockProvider();

View File

@ -26,11 +26,7 @@ function test() {
}
function end_test() {
close_manager(gManagerWindow, function() {
Services.prefs.clearUserPref("extensions.getAddons.search.url");
finish();
});
close_manager(gManagerWindow, finish);
}
function get_node(parent, anonid) {

View File

@ -29,7 +29,6 @@ function test() {
function end_test() {
close_manager(gManagerWindow, function() {
Services.prefs.clearUserPref("extensions.getAddons.search.url");
Services.prefs.clearUserPref("extensions.checkUpdateSecurity");
AddonManager.getAddonByID("addon1@tests.mozilla.org", function(aAddon) {

View File

@ -5,7 +5,6 @@
// Tests that compatibility overrides are refreshed when showing the addon
// selection UI.
const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url";
const PREF_MIN_PLATFORM_COMPAT = "extensions.minCompatiblePlatformVersion";
@ -45,8 +44,6 @@ registerCleanupFunction(function() {
if (gTestAddon)
gTestAddon.uninstall();
Services.prefs.clearUserPref(PREF_GETADDONS_CACHE_ENABLED);
Services.prefs.clearUserPref(PREF_GETADDONS_BYIDS);
Services.prefs.clearUserPref(PREF_MIN_PLATFORM_COMPAT);
});

View File

@ -21,6 +21,7 @@ const TESTROOT2 = "http://example.org/" + RELATIVE_DIR;
const CHROMEROOT = pathParts.join("/") + "/";
const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
const PREF_UPDATEURL = "extensions.update.url";
const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
const MANAGER_URI = "about:addons";
const INSTALL_URI = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
@ -34,24 +35,45 @@ var gTestStart = null;
var gUseInContentUI = !gTestInWindow && ("switchToTabHavingURI" in window);
var gDiscoveryURL = Services.prefs.getCharPref(PREF_DISCOVERURL);
var gUpdateURL = Services.prefs.getCharPref(PREF_UPDATEURL);
var gRestorePrefs = [{name: PREF_LOGGING_ENABLED},
{name: "extensions.webservice.discoverURL"},
{name: "extensions.update.url"},
{name: "extensions.getAddons.get.url"},
{name: "extensions.getAddons.search.browseURL"},
{name: "extensions.getAddons.search.url"},
{name: "extensions.getAddons.cache.enabled"},
{name: PREF_SEARCH_MAXRESULTS},
{name: PREF_STRICT_COMPAT}];
gRestorePrefs.forEach(function(aPref) {
if (!Services.prefs.prefHasUserValue(aPref.name)) {
aPref.type = "clear";
return;
}
aPref.type = Services.prefs.getPrefType(aPref.name);
if (aPref.type == Services.prefs.PREF_BOOL)
aPref.value = Services.prefs.getBoolPref(aPref.name);
else if (aPref.type == Services.prefs.PREF_INT)
aPref.value = Services.prefs.getIntPref(aPref.name);
else if (aPref.type == Services.prefs.PREF_STRING)
aPref.value = Services.prefs.getCharPref(aPref.name);
});
// Turn logging on for all tests
Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
// Turn off remote results in searches
Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 0);
registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_LOGGING_ENABLED);
try {
Services.prefs.clearUserPref(PREF_SEARCH_MAXRESULTS);
} catch (e) {}
try {
Services.prefs.clearUserPref(PREF_STRICT_COMPAT);
} catch (e) {}
Services.prefs.setCharPref(PREF_DISCOVERURL, gDiscoveryURL);
Services.prefs.setCharPref(PREF_UPDATEURL, gUpdateURL);
registerCleanupFunction(function() {
// Restore prefs
gRestorePrefs.forEach(function(aPref) {
if (aPref.type == "clear")
Services.prefs.clearUserPref(aPref.name);
else if (aPref.type == Services.prefs.PREF_BOOL)
Services.prefs.setBoolPref(aPref.name, aPref.value);
else if (aPref.type == Services.prefs.PREF_INT)
Services.prefs.setIntPref(aPref.name, aPref.value);
else if (aPref.type == Services.prefs.PREF_STRING)
Services.prefs.setCharPref(aPref.name, aPref.value);
});
// Throw an error if the add-ons manager window is open anywhere
var windows = Services.wm.getEnumerator("Addons:Manager");

View File

@ -156,6 +156,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jPostToJavaThread = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "postToJavaThread", "(Z)V");
jInitCamera = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "initCamera", "(Ljava/lang/String;III)[I");
jCloseCamera = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "closeCamera", "()V");
jIsTablet = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isTablet", "()Z");
jEnableBatteryNotifications = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableBatteryNotifications", "()V");
jDisableBatteryNotifications = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableBatteryNotifications", "()V");
jGetCurrentBatteryInformation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getCurrentBatteryInformation", "()[D");
@ -1463,6 +1464,12 @@ AndroidBridge::UnlockWindow(void* window)
return true;
}
bool
AndroidBridge::IsTablet()
{
return mJNIEnv->CallStaticBooleanMethod(mGeckoAppShellClass, jIsTablet);
}
/* Implementation file */
NS_IMPL_ISUPPORTS1(nsAndroidBridge, nsIAndroidBridge)

View File

@ -336,6 +336,8 @@ public:
PRUint16 GetNumberOfMessagesForText(const nsAString& aText);
void SendMessage(const nsAString& aNumber, const nsAString& aText);
bool IsTablet();
protected:
static AndroidBridge *sBridge;
@ -411,6 +413,7 @@ protected:
jmethodID jPostToJavaThread;
jmethodID jInitCamera;
jmethodID jCloseCamera;
jmethodID jIsTablet;
jmethodID jEnableBatteryNotifications;
jmethodID jDisableBatteryNotifications;
jmethodID jGetCurrentBatteryInformation;

View File

@ -345,6 +345,9 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI)
nsnull, getter_AddRefs(mIconRequest));
if (NS_FAILED(rv)) return rv;
// We need to request the icon be decoded (bug 573583, bug 705516).
mIconRequest->RequestDecode();
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
@ -381,10 +384,6 @@ NS_IMETHODIMP
nsMenuItemIconX::OnStartContainer(imgIRequest* aRequest,
imgIContainer* aContainer)
{
// Request a decode
NS_ABORT_IF_FALSE(aContainer, "who sent the notification then?");
aContainer->RequestDecode();
return NS_OK;
}

View File

@ -55,16 +55,12 @@
#include "mozIAsyncFavicons.h"
#include "mozilla/Preferences.h"
#include "JumpListBuilder.h"
#include "nsToolkit.h"
namespace mozilla {
namespace widget {
// SHCreateItemFromParsingName is only available on vista and up. We only load this if we
// need to call it on win7+.
JumpListLink::SHCreateItemFromParsingNamePtr JumpListLink::createItemFromParsingName = nsnull;
const PRUnichar JumpListLink::kSehllLibraryName[] = L"shell32.dll";
const char JumpListItem::kJumpListCacheDir[] = "jumpListCache";
HMODULE JumpListLink::sShellDll = nsnull;
// ISUPPORTS Impl's
NS_IMPL_ISUPPORTS1(JumpListItem,
@ -742,18 +738,11 @@ nsresult JumpListLink::GetShellItem(nsCOMPtr<nsIJumpListItem>& item, nsRefPtr<IS
NS_ENSURE_SUCCESS(rv, rv);
// Load vista+ SHCreateItemFromParsingName
if (createItemFromParsingName == nsnull) {
if (sShellDll)
return NS_ERROR_UNEXPECTED;
sShellDll = ::LoadLibraryW(kSehllLibraryName);
if (sShellDll)
createItemFromParsingName = (SHCreateItemFromParsingNamePtr)GetProcAddress(sShellDll, "SHCreateItemFromParsingName");
if (createItemFromParsingName == nsnull)
return NS_ERROR_UNEXPECTED;
}
if (!nsToolkit::VistaCreateItemFromParsingNameInit())
return NS_ERROR_UNEXPECTED;
// Create the IShellItem
if (FAILED(createItemFromParsingName(NS_ConvertASCIItoUTF16(spec).get(),
if (FAILED(nsToolkit::createItemFromParsingName(NS_ConvertASCIItoUTF16(spec).get(),
NULL, IID_PPV_ARGS(&psi))))
return NS_ERROR_INVALID_ARG;

View File

@ -118,14 +118,9 @@ public:
static nsresult GetJumpListLink(IShellItem *pItem, nsCOMPtr<nsIJumpListLink>& aLink);
protected:
typedef HRESULT (WINAPI * SHCreateItemFromParsingNamePtr)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
nsString mUriTitle;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsICryptoHash> mCryptoHash;
static const PRUnichar kSehllLibraryName[];
static HMODULE sShellDll;
static SHCreateItemFromParsingNamePtr createItemFromParsingName;
};
class JumpListShortcut : public JumpListItem, public nsIJumpListShortcut

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Seth Spitzer <sspitzer@netscape.com>
* Jim Mathies <jmathies@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -41,30 +42,53 @@
#ifndef nsFilePicker_h__
#define nsFilePicker_h__
#include <windows.h>
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
// For Vista IFileDialog interfaces
#if _WIN32_WINNT < _WIN32_WINNT_VISTA
#define _WIN32_WINNT_bak _WIN32_WINNT
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_VISTA
#define _WIN32_IE_bak _WIN32_IE
#undef _WIN32_IE
#define _WIN32_IE _WIN32_IE_IE70
#endif
#endif
#include "nsILocalFile.h"
#include "nsITimer.h"
#include "nsISimpleEnumerator.h"
#include "nsCOMArray.h"
#include "nsAutoPtr.h"
#include "nsICharsetConverterManager.h"
#include "nsBaseFilePicker.h"
#include "nsString.h"
#include "nsdefs.h"
#include <windows.h>
#include <commdlg.h>
#include <shobjidl.h>
/**
* Native Windows FileSelector wrapper
*/
class nsFilePicker : public nsBaseFilePicker
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
, public IFileDialogEvents
#endif
{
public:
nsFilePicker();
virtual ~nsFilePicker();
NS_DECL_ISUPPORTS
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
// IUnknown's QueryInterface
STDMETHODIMP QueryInterface(REFIID refiid, void** ppvResult);
#endif
// nsIFilePicker (less what's in nsBaseFilePicker)
// nsIFilePicker (less what's in nsBaseFilePicker)
NS_IMETHOD GetDefaultString(nsAString& aDefaultString);
NS_IMETHOD SetDefaultString(const nsAString& aDefaultString);
NS_IMETHOD GetDefaultExtension(nsAString& aDefaultExtension);
@ -78,6 +102,17 @@ public:
NS_IMETHOD ShowW(PRInt16 *aReturnVal);
NS_IMETHOD AppendFilter(const nsAString& aTitle, const nsAString& aFilter);
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
// IFileDialogEvents
HRESULT STDMETHODCALLTYPE OnFileOk(IFileDialog *pfd);
HRESULT STDMETHODCALLTYPE OnFolderChanging(IFileDialog *pfd, IShellItem *psiFolder);
HRESULT STDMETHODCALLTYPE OnFolderChange(IFileDialog *pfd);
HRESULT STDMETHODCALLTYPE OnSelectionChange(IFileDialog *pfd);
HRESULT STDMETHODCALLTYPE OnShareViolation(IFileDialog *pfd, IShellItem *psi, FDE_SHAREVIOLATION_RESPONSE *pResponse);
HRESULT STDMETHODCALLTYPE OnTypeChange(IFileDialog *pfd);
HRESULT STDMETHODCALLTYPE OnOverwrite(IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse);
#endif
protected:
enum PickerType {
PICKER_TYPE_OPEN,
@ -90,13 +125,28 @@ protected:
PRInt16 aMode);
static void GetQualifiedPath(const PRUnichar *aInPath, nsString &aOutPath);
void GetFilterListArray(nsString& aFilterList);
bool GetFileName(OPENFILENAMEW* ofn, PickerType aType);
bool FilePickerWrapper(OPENFILENAMEW* ofn, PickerType aType);
bool ShowFolderPicker(const nsString& aInitialDir);
bool ShowXPFolderPicker(const nsString& aInitialDir);
bool ShowFilePicker(const nsString& aInitialDir);
bool ShowXPFilePicker(const nsString& aInitialDir);
void AppendXPFilter(const nsAString& aTitle, const nsAString& aFilter);
void RememberLastUsedDirectory();
bool IsPrivacyModeEnabled();
bool IsDefaultPathLink();
bool IsDefaultPathHtml();
void SetDialogHandle(HWND aWnd);
bool ClosePickerIfNeeded(bool aIsXPDialog);
static void PickerCallbackTimerFunc(nsITimer *aTimer, void *aPicker);
static UINT_PTR CALLBACK MultiFilePickerHook(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
static UINT_PTR CALLBACK FilePickerHook(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
nsCOMPtr<nsIWidget> mParentWidget;
nsString mTitle;
PRInt16 mMode;
nsCString mFile;
nsString mDefault;
nsString mDefaultFilePath;
nsString mDefaultFilename;
nsString mDefaultExtension;
nsString mFilterList;
PRInt16 mSelectedType;
@ -104,22 +154,50 @@ protected:
static char mLastUsedDirectory[];
nsString mUnicodeFile;
static PRUnichar *mLastUsedUnicodeDirectory;
};
HWND mDlgWnd;
// The constructor will obtain the working path, the destructor
// will set the working path back to what it used to be.
class AutoRestoreWorkingPath
{
public:
AutoRestoreWorkingPath();
~AutoRestoreWorkingPath();
inline bool HasWorkingPath() const
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
class ComDlgFilterSpec
{
return mWorkingPath != NULL;
}
public:
ComDlgFilterSpec() :
mSpecList(nsnull),
mLength(0) {}
~ComDlgFilterSpec() {
free(mSpecList);
}
const PRUint32 Length() {
return mLength;
}
private:
nsAutoArrayPtr<PRUnichar> mWorkingPath;
const bool IsEmpty() {
return (mLength == 0);
}
const COMDLG_FILTERSPEC* get() {
return mSpecList;
}
void Append(const nsAString& aTitle, const nsAString& aFilter);
private:
COMDLG_FILTERSPEC* mSpecList;
nsAutoTArray<nsString, 2> mStrings;
PRUint32 mLength;
};
ComDlgFilterSpec mComFilterList;
DWORD mFDECookie;
#endif
};
#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
#if defined(_WIN32_WINNT_bak)
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_bak
#undef _WIN32_IE
#define _WIN32_IE _WIN32_IE_bak
#endif
#endif
#endif // nsFilePicker_h__

View File

@ -54,11 +54,14 @@
#include <unknwn.h>
nsToolkit* nsToolkit::gToolkit = nsnull;
HINSTANCE nsToolkit::mDllInstance = 0;
static const unsigned long kD3DUsageDelay = 5000;
// SHCreateItemFromParsingName is only available on vista and up.
nsToolkit::SHCreateItemFromParsingNamePtr nsToolkit::createItemFromParsingName = nsnull;
const PRUnichar nsToolkit::kSehllLibraryName[] = L"shell32.dll";
HMODULE nsToolkit::sShellDll = nsnull;
static void
StartAllowingD3D9(nsITimer *aTimer, void *aClosure)
{
@ -122,6 +125,24 @@ nsToolkit::StartAllowingD3D9()
nsWindow::StartAllowingD3D9(false);
}
// Load and store Vista+ SHCreateItemFromParsingName
bool
nsToolkit::VistaCreateItemFromParsingNameInit()
{
if (createItemFromParsingName)
return true;
if (sShellDll)
return false;
sShellDll = LoadLibraryW(kSehllLibraryName);
if (!sShellDll)
return false;
createItemFromParsingName = (SHCreateItemFromParsingNamePtr)
GetProcAddress(sShellDll, "SHCreateItemFromParsingName");
if (createItemFromParsingName == nsnull)
return false;
return true;
}
//-------------------------------------------------------------------------
//
// Return the nsToolkit for the current thread. If a toolkit does not

View File

@ -43,7 +43,8 @@
#include "nsITimer.h"
#include "nsCOMPtr.h"
#include <windows.h>
#include <shobjidl.h>
#include <imm.h>
// Avoid including windowsx.h to prevent macro pollution
@ -54,15 +55,6 @@
#define GET_Y_LPARAM(pt) (short(HIWORD(pt)))
#endif
// we used to use MAX_PATH
// which works great for one file
// but for multiple files, the format is
// dirpath\0\file1\0file2\0...filen\0\0
// and that can quickly be more than MAX_PATH (260)
// see bug #172001 for more details
#define FILE_BUFFER_SIZE 4096
/**
* Makes sure exit/enter mouse messages are always dispatched.
* In the case where the mouse has exited the outer most window the
@ -121,12 +113,18 @@ public:
static void Startup(HMODULE hModule);
static void Shutdown();
static void StartAllowingD3D9();
static bool VistaCreateItemFromParsingNameInit();
typedef HRESULT (WINAPI * SHCreateItemFromParsingNamePtr)(PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
static SHCreateItemFromParsingNamePtr createItemFromParsingName;
protected:
static nsToolkit* gToolkit;
nsCOMPtr<nsITimer> mD3D9Timer;
MouseTrailer mMouseTrailer;
static const PRUnichar kSehllLibraryName[];
static HMODULE sShellDll;
};
#endif // TOOLKIT_H

View File

@ -310,6 +310,7 @@ public:
void PickerOpen();
void PickerClosed();
bool const DestroyCalled() { return mDestroyCalled; }
protected:
// A magic number to identify the FAKETRACKPOINTSCROLLABLE window created

View File

@ -124,6 +124,8 @@ _CHROME_FILES += taskbar_previews.xul \
$(NULL)
_TEST_FILES += test_bug565392.html \
test_picker_no_crash.html \
window_picker_no_crash_child.html \
$(NULL)
endif

View File

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for crashes when the parent window of a file picker is closed via script</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<script type="application/javascript">
SimpleTest.waitForExplicitFinish();
var childWindow;
function testStepOne() {
childWindow = window.open('window_picker_no_crash_child.html', 'childWindow', 'width=300,height=150');
SimpleTest.waitForFocus(testStepTwo, childWindow);
}
function testStepTwo() {
childWindow.document.form1.uploadbox.click();
// This should not crash the browser
childWindow.close();
setTimeout("testStepThree();", 5000);
}
function testStepThree() {
ok(true, "browser didn't crash");
SimpleTest.finish();
}
SimpleTest.waitForFocus(testStepOne);
</script>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<title>Picker window</title>
</head>
<body>
<form name="form1">
<input type="file" name="uploadbox">
</form>
</body>
</html>

View File

@ -197,11 +197,11 @@ nsSystemInfo::Init()
str.Append(NS_LITERAL_STRING(" ("));
str.AppendInt(version);
str.Append(NS_LITERAL_STRING(")"));
}
}
SetPropertyAsAString(NS_LITERAL_STRING("shellVersion"), str);
}
bool isTablet = mozilla::AndroidBridge::Bridge()->IsTablet();
SetPropertyAsBool(NS_LITERAL_STRING("isTablet"), isTablet);
}
#endif
return NS_OK;

View File

@ -434,6 +434,9 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
NS_NAMED_LITERAL_STRING(kOs, "os");
NS_NAMED_LITERAL_STRING(kOsVersion, "osversion");
NS_NAMED_LITERAL_STRING(kABI, "abi");
#if defined(MOZ_WIDGET_ANDROID)
NS_NAMED_LITERAL_STRING(kTablet, "tablet");
#endif
// Obsolete
NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers");
@ -498,8 +501,10 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
gtk_major_version,
gtk_minor_version);
#elif defined(MOZ_WIDGET_ANDROID)
bool isTablet = false;
if (mozilla::AndroidBridge::Bridge()) {
mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion);
isTablet = mozilla::AndroidBridge::Bridge()->IsTablet();
}
#endif
@ -587,6 +592,9 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
TriState stOsVersion = eUnspecified;
TriState stOs = eUnspecified;
TriState stABI = eUnspecified;
#if defined(MOZ_WIDGET_ANDROID)
TriState stTablet = eUnspecified;
#endif
bool platform = false;
bool contentAccessible = false;
@ -602,6 +610,14 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion))
continue;
#if defined(MOZ_WIDGET_ANDROID)
bool tablet = false;
if (CheckFlag(kTablet, wtoken, tablet)) {
stTablet = (tablet == isTablet) ? eOK : eBad;
continue;
}
#endif
if (directive->contentflags &&
(CheckFlag(kPlatform, wtoken, platform) ||
CheckFlag(kContentAccessible, wtoken, contentAccessible)))
@ -627,6 +643,9 @@ ParseManifest(NSLocationType type, FileLocation &file, char* buf, bool aChromeOn
stGeckoVersion == eBad ||
stOs == eBad ||
stOsVersion == eBad ||
#ifdef MOZ_WIDGET_ANDROID
stTablet == eBad ||
#endif
stABI == eBad)
continue;