Merge last PGO-green changeset of mozilla-inbound to mozilla-central

This commit is contained in:
Ed Morley 2013-01-08 09:26:15 +00:00
commit 1ee741e692
52 changed files with 916 additions and 276 deletions

View File

@ -24,7 +24,7 @@ ActivitiesDialog.prototype = {
let choices = [];
activity.list.forEach(function(item) {
choices.push({ title: item.title, icon: item.icon });
choices.push({ manifest: item.manifest, icon: item.icon });
});

View File

@ -773,6 +773,11 @@ DownloadsDataCtor.prototype = {
ensurePersistentDataLoaded:
function DD_ensurePersistentDataLoaded(aActiveOnly)
{
if (this == PrivateDownloadsData) {
Cu.reportError("ensurePersistentDataLoaded should not be called on PrivateDownloadsData");
return;
}
if (this._pendingStatement) {
// We are already in the process of reloading all downloads.
return;
@ -787,9 +792,7 @@ DownloadsDataCtor.prototype = {
// Reload the list using the Download Manager service. The list is
// returned in no particular order.
let downloads = this._isPrivate ?
Services.downloads.activePrivateDownloads :
Services.downloads.activeDownloads;
let downloads = Services.downloads.activeDownloads;
while (downloads.hasMoreElements()) {
let download = downloads.getNext().QueryInterface(Ci.nsIDownload);
this._getOrAddDataItem(download, true);
@ -807,9 +810,7 @@ DownloadsDataCtor.prototype = {
// columns are read in the _initFromDataRow method of DownloadsDataItem.
// Order by descending download identifier so that the most recent
// downloads are notified first to the listening views.
let dbConnection = this._isPrivate ?
Services.downloads.privateDBConnection :
Services.downloads.DBConnection;
let dbConnection = Services.downloads.DBConnection;
let statement = dbConnection.createAsyncStatement(
"SELECT guid, target, name, source, referrer, state, "
+ "startTime, endTime, currBytes, maxBytes "

View File

@ -336,8 +336,8 @@ interface nsIFrameScriptLoader : nsISupports
void removeDelayedFrameScript(in AString aURL);
};
[scriptable, builtinclass, uuid(5f552699-01a2-4f17-833b-ddb3fa0d98b2)]
interface nsIPermissionChecker : nsISupports
[scriptable, builtinclass, uuid(e2ccdade-4c16-11e2-9ae0-23151c6d6e1d)]
interface nsIProcessChecker : nsISupports
{
/**
@ -361,4 +361,25 @@ interface nsIPermissionChecker : nsISupports
*/
boolean assertPermission(in DOMString aPermission);
/**
* Return true iff the "remote" process has |aManifestURL|. This is
* intended to be used by JS implementations of cross-process DOM
* APIs, like so
*
* recvFooRequest: function(message) {
* if (!message.target.assertContainApp("foo")) {
* return false;
* }
* // service foo request
*
* This interface only returns meaningful data when our content is
* in a separate process. If it shares the same OS process as us,
* then applying this manifest URL check doesn't add any security,
* though it doesn't hurt anything either.
*
* Note: If the remote content process does *not* contain |aManifestURL|,
* it will be killed as a precaution.
*/
boolean assertContainApp(in DOMString aManifestURL);
};

View File

@ -77,7 +77,7 @@
#include "Layers.h"
#include "AppProcessPermissions.h"
#include "AppProcessChecker.h"
#include "ContentParent.h"
#include "TabParent.h"
#include "mozilla/GuardObjects.h"
@ -2314,6 +2314,13 @@ nsFrameLoader::CheckPermission(const nsAString& aPermission)
NS_ConvertUTF16toUTF8(aPermission).get());
}
bool
nsFrameLoader::CheckManifestURL(const nsAString& aManifestURL)
{
return AssertAppProcessManifestURL(GetRemoteBrowser(),
NS_ConvertUTF16toUTF8(aManifestURL).get());
}
NS_IMETHODIMP
nsFrameLoader::GetMessageManager(nsIMessageSender** aManager)
{
@ -2550,6 +2557,12 @@ nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
void
nsFrameLoader::ResetPermissionManagerStatus()
{
// The resetting of the permissions status can run only
// in the main process.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
return;
}
// Finding the new app Id:
// . first we check if the owner is an app frame
// . second, we check if the owner is a browser frame

View File

@ -189,7 +189,7 @@ public:
virtual bool DoSendAsyncMessage(const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData);
virtual bool CheckPermission(const nsAString& aPermission);
virtual bool CheckManifestURL(const nsAString& aManifestURL);
/**
* Called from the layout frame associated with this frame loader;

View File

@ -7,7 +7,7 @@
#include "nsFrameMessageManager.h"
#include "AppProcessPermissions.h"
#include "AppProcessChecker.h"
#include "ContentChild.h"
#include "ContentParent.h"
#include "nsContentUtils.h"
@ -107,8 +107,8 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameMessageManager)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIFrameScriptLoader,
mChrome && !mIsProcessManager)
/* Message senders in the chrome process support nsIPermissionChecker. */
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIPermissionChecker,
/* Message senders in the chrome process support nsIProcessChecker. */
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIProcessChecker,
mChrome && !mIsBroadcaster)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(ChromeMessageBroadcaster,
@ -423,12 +423,14 @@ nsFrameMessageManager::Atob(const nsAString& aAsciiString,
return NS_OK;
}
// nsIPermissionChecker
// nsIProcessChecker
NS_IMETHODIMP
nsFrameMessageManager::AssertPermission(const nsAString& aPermission, bool* aHasPermission)
nsresult
nsFrameMessageManager::AssertProcessInternal(ProcessCheckerType aType,
const nsAString& aCapability,
bool* aValid)
{
*aHasPermission = false;
*aValid = false;
// This API is only supported for message senders in the chrome process.
if (!mChrome || mIsBroadcaster) {
@ -437,10 +439,37 @@ nsFrameMessageManager::AssertPermission(const nsAString& aPermission, bool* aHas
if (!mCallback) {
return NS_ERROR_NOT_AVAILABLE;
}
*aHasPermission = mCallback->CheckPermission(aPermission);
switch (aType) {
case PROCESS_CHECKER_PERMISSION:
*aValid = mCallback->CheckPermission(aCapability);
break;
case PROCESS_CHECKER_MANIFEST_URL:
*aValid = mCallback->CheckManifestURL(aCapability);
break;
default:
break;
}
return NS_OK;
}
NS_IMETHODIMP
nsFrameMessageManager::AssertPermission(const nsAString& aPermission,
bool* aHasPermission)
{
return AssertProcessInternal(PROCESS_CHECKER_PERMISSION,
aPermission,
aHasPermission);
}
NS_IMETHODIMP
nsFrameMessageManager::AssertContainApp(const nsAString& aManifestURL,
bool* aHasManifestURL)
{
return AssertProcessInternal(PROCESS_CHECKER_MANIFEST_URL,
aManifestURL,
aHasManifestURL);
}
class MMListenerRemover
{
public:
@ -1100,6 +1129,11 @@ public:
return true;
}
bool CheckManifestURL(const nsAString& aManifestURL)
{
// In a single-process scenario, the child always has all capabilities.
return true;
}
};

View File

@ -66,6 +66,11 @@ public:
{
return false;
}
virtual bool CheckManifestURL(const nsAString& aManifestURL)
{
return false;
}
};
} // namespace ipc
@ -86,7 +91,7 @@ struct nsMessageListenerInfo
class nsFrameMessageManager MOZ_FINAL : public nsIContentFrameMessageManager,
public nsIMessageBroadcaster,
public nsIFrameScriptLoader,
public nsIPermissionChecker
public nsIProcessChecker
{
typedef mozilla::dom::StructuredCloneData StructuredCloneData;
public:
@ -152,7 +157,7 @@ public:
NS_DECL_NSISYNCMESSAGESENDER
NS_DECL_NSICONTENTFRAMEMESSAGEMANAGER
NS_DECL_NSIFRAMESCRIPTLOADER
NS_DECL_NSIPERMISSIONCHECKER
NS_DECL_NSIPROCESSCHECKER
static nsFrameMessageManager*
NewProcessMessageManager(mozilla::dom::ContentParent* aProcess);
@ -226,6 +231,14 @@ public:
static nsFrameMessageManager* sChildProcessManager;
static nsFrameMessageManager* sSameProcessParentManager;
static nsTArray<nsCOMPtr<nsIRunnable> >* sPendingSameProcessAsyncMessages;
private:
enum ProcessCheckerType {
PROCESS_CHECKER_PERMISSION,
PROCESS_CHECKER_MANIFEST_URL
};
nsresult AssertProcessInternal(ProcessCheckerType aType,
const nsAString& aCapability,
bool* aValid);
};
void

View File

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<title>Test for the nsIPermissionChecker part of Message Managers</title>
<title>Test for the nsIProcessChecker part of Message Managers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>

View File

@ -16,7 +16,9 @@
#include "nsMappedAttributes.h"
#include "nsRuleData.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(SharedList)
NS_IMPL_NS_NEW_HTML_ELEMENT(OList)
NS_IMPL_NS_NEW_HTML_ELEMENT(DList)
NS_IMPL_NS_NEW_HTML_ELEMENT(UList)
DOMCI_DATA(HTMLOListElement, mozilla::dom::HTMLSharedListElement)
DOMCI_DATA(HTMLDListElement, mozilla::dom::HTMLSharedListElement)
DOMCI_DATA(HTMLUListElement, mozilla::dom::HTMLSharedListElement)
@ -62,7 +64,9 @@ NS_INTERFACE_TABLE_HEAD(HTMLSharedListElement)
NS_HTML_CONTENT_INTERFACE_MAP_END
NS_IMPL_ELEMENT_CLONE(HTMLSharedListElement)
NS_IMPL_ELEMENT_CLONE(HTMLOListElement)
NS_IMPL_ELEMENT_CLONE(HTMLDListElement)
NS_IMPL_ELEMENT_CLONE(HTMLUListElement)
NS_IMPL_BOOL_ATTR(HTMLSharedListElement, Compact, compact)

View File

@ -55,7 +55,6 @@ public:
nsAttrValue& aResult);
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
virtual nsXPCClassInfo* GetClassInfo()
{
return static_cast<nsXPCClassInfo*>(GetClassInfoInternal());
@ -99,10 +98,20 @@ public:
{
SetHTMLBoolAttr(nsGkAtoms::compact, aCompact, rv);
}
protected:
virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
bool *aTriedToWrap) MOZ_OVERRIDE = 0;
};
class HTMLDListElement MOZ_FINAL : public HTMLSharedListElement
{
public:
HTMLDListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: HTMLSharedListElement(aNodeInfo)
{
}
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
bool *aTriedToWrap) MOZ_OVERRIDE;
@ -110,6 +119,12 @@ protected:
class HTMLOListElement MOZ_FINAL : public HTMLSharedListElement
{
public:
HTMLOListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: HTMLSharedListElement(aNodeInfo)
{
}
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
bool *aTriedToWrap) MOZ_OVERRIDE;
@ -117,6 +132,12 @@ protected:
class HTMLUListElement MOZ_FINAL : public HTMLSharedListElement
{
public:
HTMLUListElement(already_AddRefed<nsINodeInfo> aNodeInfo)
: HTMLSharedListElement(aNodeInfo)
{
}
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
protected:
virtual JSObject* WrapNode(JSContext *aCx, JSObject *aScope,
bool *aTriedToWrap) MOZ_OVERRIDE;

View File

@ -1910,7 +1910,6 @@ NS_NewHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo,
mozilla::dom::FromParser aFromParser = mozilla::dom::NOT_FROM_PARSER);
NS_DECLARE_NS_NEW_HTML_ELEMENT(Shared)
NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedList)
NS_DECLARE_NS_NEW_HTML_ELEMENT(SharedObject)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Anchor)
@ -1925,6 +1924,7 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(Canvas)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Mod)
NS_DECLARE_NS_NEW_HTML_ELEMENT(DataList)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Div)
NS_DECLARE_NS_NEW_HTML_ELEMENT(DList)
NS_DECLARE_NS_NEW_HTML_ELEMENT(FieldSet)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Font)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Form)
@ -1947,6 +1947,7 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(MenuItem)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Meta)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Meter)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Object)
NS_DECLARE_NS_NEW_HTML_ELEMENT(OList)
NS_DECLARE_NS_NEW_HTML_ELEMENT(OptGroup)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Option)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Output)
@ -1971,6 +1972,7 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT(TextArea)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Tfoot)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Thead)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Title)
NS_DECLARE_NS_NEW_HTML_ELEMENT(UList)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Unknown)
#if defined(MOZ_MEDIA)
NS_DECLARE_NS_NEW_HTML_ELEMENT(Video)

View File

@ -1076,7 +1076,7 @@ nsHTMLInputElement::ConvertStringToNumber(nsAString& aValue,
return false;
}
break;
return true;
}
case NS_FORM_INPUT_DATE:
{
@ -1091,32 +1091,40 @@ nsHTMLInputElement::ConvertStringToNumber(nsAString& aValue,
}
JSObject* date = JS_NewDateObjectMsec(ctx, 0);
if (!date) {
JS_ClearPendingException(ctx);
return false;
}
jsval rval;
jsval fullYear[3];
fullYear[0].setInt32(year);
fullYear[1].setInt32(month-1);
fullYear[2].setInt32(day);
if (!JS::Call(ctx, date, "setUTCFullYear", 3, fullYear, &rval)) {
JS_ClearPendingException(ctx);
return false;
}
jsval timestamp;
if (!JS::Call(ctx, date, "getTime", 0, nullptr, &timestamp)) {
JS_ClearPendingException(ctx);
return false;
}
if (!timestamp.isNumber()) {
if (!timestamp.isNumber() || MOZ_DOUBLE_IS_NaN(timestamp.toNumber())) {
return false;
}
aResultValue = timestamp.toNumber();
return true;
}
break;
default:
return false;
}
return true;
MOZ_NOT_REACHED();
return false;
}
double
@ -1242,6 +1250,7 @@ nsHTMLInputElement::ConvertNumberToString(double aValue,
JSObject* date = JS_NewDateObjectMsec(ctx, aValue);
if (!date) {
JS_ClearPendingException(ctx);
return false;
}
@ -1249,6 +1258,14 @@ nsHTMLInputElement::ConvertNumberToString(double aValue,
if (!JS::Call(ctx, date, "getUTCFullYear", 0, nullptr, &year) ||
!JS::Call(ctx, date, "getUTCMonth", 0, nullptr, &month) ||
!JS::Call(ctx, date, "getUTCDate", 0, nullptr, &day)) {
JS_ClearPendingException(ctx);
return false;
}
if (!year.isNumber() || !month.isNumber() || !day.isNumber() ||
MOZ_DOUBLE_IS_NaN(year.toNumber()) ||
MOZ_DOUBLE_IS_NaN(month.toNumber()) ||
MOZ_DOUBLE_IS_NaN(day.toNumber())) {
return false;
}
@ -1280,12 +1297,19 @@ nsHTMLInputElement::GetValueAsDate(JSContext* aCtx, jsval* aDate)
}
JSObject* date = JS_NewDateObjectMsec(aCtx, 0);
if (!date) {
JS_ClearPendingException(aCtx);
aDate->setNull();
return NS_OK;
}
jsval rval;
jsval fullYear[3];
fullYear[0].setInt32(year);
fullYear[1].setInt32(month-1);
fullYear[2].setInt32(day);
if(!JS::Call(aCtx, date, "setUTCFullYear", 3, fullYear, &rval)) {
JS_ClearPendingException(aCtx);
aDate->setNull();
return NS_OK;
}
@ -1301,15 +1325,22 @@ nsHTMLInputElement::SetValueAsDate(JSContext* aCtx, const jsval& aDate)
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
if (aDate.isNullOrUndefined()) {
return SetValue(EmptyString());
}
// TODO: return TypeError when HTMLInputElement is converted to WebIDL, see
// bug 826302.
if (!aDate.isObject() || !JS_ObjectIsDate(aCtx, &aDate.toObject())) {
SetValue(EmptyString());
return NS_OK;
return NS_ERROR_INVALID_ARG;
}
JSObject& date = aDate.toObject();
jsval timestamp;
bool ret = JS::Call(aCtx, &date, "getTime", 0, nullptr, &timestamp);
if (!ret || !timestamp.isNumber() || MOZ_DOUBLE_IS_NaN(timestamp.toNumber())) {
if (!JS::Call(aCtx, &date, "getTime", 0, nullptr, &timestamp) ||
!timestamp.isNumber() || MOZ_DOUBLE_IS_NaN(timestamp.toNumber())) {
JS_ClearPendingException(aCtx);
SetValue(EmptyString());
return NS_OK;
}

View File

@ -3570,9 +3570,10 @@ void nsHTMLMediaElement::UpdateAudioChannelPlayingState()
// The nsHTMLMediaElement is registered to the AudioChannelService only on B2G.
#ifdef MOZ_B2G
bool playingThroughTheAudioChannel =
(mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
!mPaused &&
!IsPlaybackEnded());
(!mPaused &&
(HasAttr(kNameSpaceID_None, nsGkAtoms::loop) ||
mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
!IsPlaybackEnded()));
if (playingThroughTheAudioChannel != mPlayingThroughTheAudioChannel) {
mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;

View File

@ -176,6 +176,9 @@ function checkSet()
// the corresponding date string is the empty string
[ -62135596800001, "" ],
// Invalid dates.
// We set the value to something different than the empty string because
// NaN should set the value to the empty string.
[ 86400000, "1970-01-02" ],
[ NaN, "" ],
];
@ -186,9 +189,61 @@ function checkSet()
+ data[1]);
}
element.value = "test";
element.valueAsDate = null;
is(element.value, "", "valueAsDate should set the value to the empty string");
element.value = "test";
element.valueAsDate = undefined;
is(element.value, "", "valueAsDate should set the value to the empty string");
var illegalValues = [
"foobar", 42, {}, function() { return 42; }, function() { return Date(); }
];
for (value of illegalValues) {
try {
var caught = false;
element.valueAsDate = value;
} catch(e) {
caught = true;
}
ok(caught, "Assigning " + value + " to .valueAsDate should throw");
}
}
function checkWithBustedPrototype()
{
var element = document.createElement('input');
element.type = 'date';
var witnessDate = new Date();
Date.prototype.getUTCFullYear = function() { return {}; };
Date.prototype.getUTCMonth = function() { return {}; };
Date.prototype.getUTCDate = function() { return {}; };
Date.prototype.getTime = function() { return {}; };
Date.prototype.setUTCFullYear = function(y,m,d) { };
element.valueAsDate = new Date();
todo_isnot(element.valueAsDate, null, ".valueAsDate should not return null");
// TODO: check the Date object value (UTCFullYear, UTCMonth and UTCDate)
// when .valueAsDate will stop returning null.
// Same test as above but using NaN instead of {}.
Date.prototype.getUTCFullYear = function() { return NaN; };
Date.prototype.getUTCMonth = function() { return NaN; };
Date.prototype.getUTCDate = function() { return NaN; };
Date.prototype.getTime = function() { return NaN; };
Date.prototype.setUTCFullYear = function(y,m,d) { };
element.valueAsDate = new Date();
todo_isnot(element.valueAsDate, null, ".valueAsDate should not return null");
// TODO: check the Date object value (UTCFullYear, UTCMonth and UTCDate)
// when .valueAsDate will stop returning null.
}
SimpleTest.waitForExplicitFinish();
@ -196,6 +251,7 @@ SpecialPowers.pushPrefEnv({'set': [["dom.experimental_forms", true]]}, function(
checkAvailability();
checkGet();
checkSet();
checkWithBustedPrototype();
SimpleTest.finish();
});

View File

@ -573,10 +573,6 @@ bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
{
status_t err;
if (!mAudioBuffer) {
return false;
}
if (mAudioMetadataRead && aSeekTimeUs == -1) {
// Use the data read into the buffer during metadata time
err = OK;
@ -595,7 +591,7 @@ bool OmxDecoder::ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs)
aSeekTimeUs = -1;
if (err == OK && mAudioBuffer->range_length() != 0) {
if (err == OK && mAudioBuffer && mAudioBuffer->range_length() != 0) {
int64_t timeUs;
if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs))
return false;

View File

@ -52,7 +52,6 @@ ActivitiesDb.prototype = {
* id: String
* manifest: String
* name: String
* title: String
* icon: String
* description: jsval
* }
@ -94,7 +93,6 @@ ActivitiesDb.prototype = {
let object = {
manifest: aObject.manifest,
name: aObject.name,
title: aObject.title || "",
icon: aObject.icon || "",
description: aObject.description
};
@ -140,7 +138,6 @@ ActivitiesDb.prototype = {
txn.result.options.push({
manifest: result.manifest,
title: result.title,
icon: result.icon,
description: result.description
});

View File

@ -83,19 +83,23 @@ this.AlarmService = {
receiveMessage: function receiveMessage(aMessage) {
debug("receiveMessage(): " + aMessage.name);
let json = aMessage.json;
// To prevent hacked child processes from sending commands to parent
// to schedule alarms, we need to check their installed permissions.
// To prevent the hacked child process from sending commands to parent
// to schedule alarms, we need to check its permission and manifest URL.
if (["AlarmsManager:GetAll", "AlarmsManager:Add", "AlarmsManager:Remove"]
.indexOf(aMessage.name) != -1) {
if (!aMessage.target.assertPermission("alarms")) {
debug("Got message from a child process with no 'alarms' permission.");
return null;
}
if (!aMessage.target.assertContainApp(json.manifestURL)) {
debug("Got message from a child process containing illegal manifest URL.");
return null;
}
}
let mm = aMessage.target.QueryInterface(Ci.nsIMessageSender);
let json = aMessage.json;
switch (aMessage.name) {
case "AlarmsManager:GetAll":
this._db.getAll(

View File

@ -496,7 +496,6 @@ this.DOMApplicationRegistry = {
if (aRunUpdate) {
activitiesToRegister.push({ "manifest": aApp.manifestURL,
"name": activity,
"title": manifest.name,
"icon": manifest.iconURLForSize(128),
"description": description });
}

View File

@ -3810,7 +3810,7 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageSender, nsISupports)
DOM_CLASSINFO_MAP_ENTRY(nsIPermissionChecker)
DOM_CLASSINFO_MAP_ENTRY(nsIProcessChecker)
DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader)
DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager)
DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender)

View File

@ -1965,6 +1965,107 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
return rv;
}
nsresult
nsJSContext::CallEventHandler(nsISupports* aTarget, JSObject* aScope,
JSObject* aHandler, nsIArray* aargv,
nsIVariant** arv)
{
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
if (!mScriptsEnabled) {
return NS_OK;
}
SAMPLE_LABEL("JS", "CallEventHandler");
nsAutoMicroTask mt;
xpc_UnmarkGrayObject(aScope);
xpc_UnmarkGrayObject(aHandler);
XPCAutoRequest ar(mContext);
JSObject* target = nullptr;
nsresult rv = JSObjectFromInterface(aTarget, aScope, &target);
NS_ENSURE_SUCCESS(rv, rv);
JS::AutoObjectRooter targetVal(mContext, target);
jsval rval = JSVAL_VOID;
// This one's a lot easier than EvaluateString because we don't have to
// hassle with principals: they're already compiled into the JS function.
// xxxmarkh - this comment is no longer true - principals are not used at
// all now, and never were in some cases.
nsCxPusher pusher;
if (!pusher.Push(mContext, true))
return NS_ERROR_FAILURE;
// check if the event handler can be run on the object in question
rv = sSecurityManager->CheckFunctionAccess(mContext, aHandler, target);
nsJSContext::TerminationFuncHolder holder(this);
if (NS_SUCCEEDED(rv)) {
// Convert args to jsvals.
uint32_t argc = 0;
jsval *argv = nullptr;
JSObject *funobj = aHandler;
jsval funval = OBJECT_TO_JSVAL(funobj);
JSAutoCompartment ac(mContext, funobj);
if (!JS_WrapObject(mContext, &target)) {
ReportPendingException();
return NS_ERROR_FAILURE;
}
Maybe<nsRootedJSValueArray> tempStorage;
// Use |target| as the scope for wrapping the arguments, since aScope is
// the safe scope in many cases, which isn't very useful. Wrapping aTarget
// was OK because those typically have PreCreate methods that give them the
// right scope anyway, and we want to make sure that the arguments end up
// in the same scope as aTarget.
rv = ConvertSupportsTojsvals(aargv, target, &argc, &argv, tempStorage);
NS_ENSURE_SUCCESS(rv, rv);
for (uint32_t i = 0; i < argc; i++) {
if (!JSVAL_IS_PRIMITIVE(argv[i])) {
xpc_UnmarkGrayObject(JSVAL_TO_OBJECT(argv[i]));
}
}
++mExecuteDepth;
bool ok = ::JS_CallFunctionValue(mContext, target,
funval, argc, argv, &rval);
--mExecuteDepth;
if (!ok) {
// Don't pass back results from failed calls.
rval = JSVAL_VOID;
// Tell the caller that the handler threw an error.
rv = NS_ERROR_FAILURE;
} else if (rval == JSVAL_NULL) {
*arv = nullptr;
} else if (!JS_WrapValue(mContext, &rval)) {
rv = NS_ERROR_FAILURE;
} else {
rv = nsContentUtils::XPConnect()->JSToVariant(mContext, rval, arv);
}
// Tell XPConnect about any pending exceptions. This is needed
// to avoid dropping JS exceptions in case we got here through
// nested calls through XPConnect.
if (NS_FAILED(rv))
ReportPendingException();
}
pusher.Pop();
// ScriptEvaluated needs to come after we pop the stack
ScriptEvaluated(true);
return rv;
}
nsresult
nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, JSObject* aScope,
JSObject* aHandler,

0
dom/camera/DOMCameraControl.cpp Executable file → Normal file
View File

View File

@ -282,6 +282,7 @@ nsGonkCameraControl::Init()
nsGonkCameraControl::~nsGonkCameraControl()
{
DOM_CAMERA_LOGT("%s:%d : this=%p, mHwHandle = %d\n", __func__, __LINE__, this, mHwHandle);
ReleaseHardwareImpl(nullptr);
if (mRwLock) {
PRRWLock* lock = mRwLock;
@ -1331,7 +1332,7 @@ nsGonkCameraControl::ReleaseHardwareImpl(ReleaseHardwareTask* aReleaseHardware)
StopPreviewInternal(true /* forced */);
// release the hardware handle
GonkCameraHardware::ReleaseHandle(mHwHandle);
GonkCameraHardware::ReleaseHandle(mHwHandle, true /* unregister */);
if (aReleaseHardware && aReleaseHardware->mOnSuccessCb) {
nsCOMPtr<nsIRunnable> releaseHardwareResult = new ReleaseHardwareResult(aReleaseHardware->mOnSuccessCb, mWindowId);

View File

@ -234,7 +234,8 @@ GonkCameraHardware* GonkCameraHardware::sHw = nullptr;
uint32_t GonkCameraHardware::sHwHandle = 0;
void
GonkCameraHardware::ReleaseHandle(uint32_t aHwHandle)
GonkCameraHardware::ReleaseHandle(uint32_t aHwHandle,
bool aUnregisterTarget = false)
{
GonkCameraHardware* hw = GetHardware(aHwHandle);
DOM_CAMERA_LOGI("%s: aHwHandle = %d, hw = %p (sHwHandle = %d)\n", __func__, aHwHandle, (void*)hw, sHwHandle);
@ -253,6 +254,9 @@ GonkCameraHardware::ReleaseHandle(uint32_t aHwHandle)
window->abandon();
}
DOM_CAMERA_LOGT("%s: after: sHwHandle = %d\n", __func__, sHwHandle);
if (aUnregisterTarget) {
hw->mTarget = nullptr;
}
delete hw; // destroy the camera hardware instance
}

View File

@ -51,7 +51,7 @@ protected:
public:
virtual void OnNewFrame() MOZ_OVERRIDE;
static void ReleaseHandle(uint32_t aHwHandle);
static void ReleaseHandle(uint32_t aHwHandle, bool aUnregisterTarget);
static uint32_t GetHandle(GonkCamera* aTarget, uint32_t aCamera);
/**

View File

@ -11,7 +11,7 @@
#include "mozilla/dom/ipc/Blob.h"
#include "ContentParent.h"
#include "nsProxyRelease.h"
#include "AppProcessPermissions.h"
#include "AppProcessChecker.h"
#include "mozilla/Preferences.h"
namespace mozilla {

View File

@ -12,7 +12,7 @@
#include "nsIJSContextStack.h"
#include "nsIXPConnect.h"
#include "mozilla/AppProcessPermissions.h"
#include "mozilla/AppProcessChecker.h"
#include "mozilla/Assertions.h"
#include "mozilla/unused.h"
#include "mozilla/Util.h"

View File

@ -5,7 +5,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AppProcessPermissions.h"
#include "AppProcessChecker.h"
#include "ContentParent.h"
#include "mozIApplication.h"
#include "mozilla/hal_sandbox/PHalParent.h"
@ -19,41 +19,59 @@ using namespace mozilla::services;
namespace mozilla {
bool
AssertAppProcessPermission(PBrowserParent* aActor, const char* aPermission)
AssertAppProcess(PBrowserParent* aActor,
AssertAppProcessType aType,
const char* aCapability)
{
if (!aActor) {
NS_WARNING("Testing permissions for null actor");
NS_WARNING("Testing process capability for null actor");
return false;
}
TabParent* tab = static_cast<TabParent*>(aActor);
nsCOMPtr<mozIApplication> app = tab->GetOwnOrContainingApp();
bool hasPermission = false;
bool aValid = false;
// isBrowser frames inherit their app descriptor to identify their
// data storage, but they don't inherit the permissions associated
// data storage, but they don't inherit the capability associated
// with that descriptor.
if (app && !tab->IsBrowserElement()) {
if (!NS_SUCCEEDED(app->HasPermission(aPermission, &hasPermission))) {
hasPermission = false;
switch (aType) {
case ASSERT_APP_PROCESS_PERMISSION:
if (!NS_SUCCEEDED(app->HasPermission(aCapability, &aValid))) {
aValid = false;
}
break;
case ASSERT_APP_PROCESS_MANIFEST_URL: {
nsAutoString manifestURL;
if (NS_SUCCEEDED(app->GetManifestURL(manifestURL)) &&
manifestURL.EqualsASCII(aCapability)) {
aValid = true;
}
break;
}
default:
break;
}
}
if (!hasPermission) {
printf_stderr("Security problem: Content process does not have `%s' permission. It will be killed.\n", aPermission);
if (!aValid) {
printf_stderr("Security problem: Content process does not have `%s'. It will be killed.\n", aCapability);
ContentParent* process = static_cast<ContentParent*>(aActor->Manager());
process->KillHard();
}
return hasPermission;
return aValid;
}
bool
AssertAppProcessPermission(PContentParent* aActor, const char* aPermission)
AssertAppProcess(PContentParent* aActor,
AssertAppProcessType aType,
const char* aCapability)
{
const InfallibleTArray<PBrowserParent*>& browsers =
aActor->ManagedPBrowserParent();
for (uint32_t i = 0; i < browsers.Length(); ++i) {
if (AssertAppProcessPermission(browsers[i], aPermission)) {
if (AssertAppProcess(browsers[i], aType, aCapability)) {
return true;
}
}
@ -61,9 +79,11 @@ AssertAppProcessPermission(PContentParent* aActor, const char* aPermission)
}
bool
AssertAppProcessPermission(PHalParent* aActor, const char* aPermission)
AssertAppProcess(PHalParent* aActor,
AssertAppProcessType aType,
const char* aCapability)
{
return AssertAppProcessPermission(aActor->Manager(), aPermission);
return AssertAppProcess(aActor->Manager(), aType, aCapability);
}
} // namespace mozilla

View File

@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_AppProcessChecker_h
#define mozilla_AppProcessChecker_h
namespace mozilla {
namespace dom {
class PBrowserParent;
class PContentParent;
}
namespace hal_sandbox {
class PHalParent;
}
enum AssertAppProcessType {
ASSERT_APP_PROCESS_PERMISSION,
ASSERT_APP_PROCESS_MANIFEST_URL
};
/**
* Return true iff the specified browser has the specified capability.
* If this returns false, the browser didn't have the capability and
* will be killed.
*/
bool
AssertAppProcess(mozilla::dom::PBrowserParent* aActor,
AssertAppProcessType aType,
const char* aCapability);
/**
* Return true iff any of the PBrowsers loaded in this content process
* has the specified capability. If this returns false, the process
* didn't have the capability and will be killed.
*/
bool
AssertAppProcess(mozilla::dom::PContentParent* aActor,
AssertAppProcessType aType,
const char* aCapability);
bool
AssertAppProcess(mozilla::hal_sandbox::PHalParent* aActor,
AssertAppProcessType aType,
const char* aCapability);
// NB: when adding capability checks for other IPDL actors, please add
// them to this file and have them delegate to the two functions above
// as appropriate. For example,
//
// bool AppProcessHasCapability(PNeckoParent* aActor, AssertAppProcessType aType) {
// return AssertAppProcess(aActor->Manager(), aType);
// }
/**
* Inline function for asserting the process's permission.
*/
template<typename T>
inline bool
AssertAppProcessPermission(T* aActor,
const char* aPermission) {
return AssertAppProcess(aActor,
ASSERT_APP_PROCESS_PERMISSION,
aPermission);
}
/**
* Inline function for asserting the process's manifest URL.
*/
template<typename T>
inline bool
AssertAppProcessManifestURL(T* aActor,
const char* aManifestURL) {
return AssertAppProcess(aActor,
ASSERT_APP_PROCESS_MANIFEST_URL,
aManifestURL);
}
} // namespace mozilla
#endif // mozilla_AppProcessChecker_h

View File

@ -1,54 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_AppProcessPermissions_h
#define mozilla_AppProcessPermissions_h
namespace mozilla {
namespace dom {
class PBrowserParent;
class PContentParent;
}
namespace hal_sandbox {
class PHalParent;
}
/**
* Return true iff the specified browser has the specified capability.
* If this returns false, the browser didn't have the permission and
* will be killed.
*/
bool
AssertAppProcessPermission(mozilla::dom::PBrowserParent* aActor,
const char* aPermission);
/**
* Return true iff any of the PBrowsers loaded in this content process
* has the specified capability. If this returns false, the process
* didn't have the permission and will be killed.
*/
bool
AssertAppProcessPermission(mozilla::dom::PContentParent* aActor,
const char* aPermission);
bool
AssertAppProcessPermission(mozilla::hal_sandbox::PHalParent* aActor,
const char* aPermission);
// NB: when adding capability checks for other IPDL actors, please add
// them to this file and have them delegate to the two functions above
// as appropriate. For example,
//
// bool AppProcessHasCapability(PNeckoParent* aActor) {
// return AssertAppProcessPermission(aActor->Manager());
// }
} // namespace mozilla
#endif // mozilla_AppProcessPermissions_h

View File

@ -17,7 +17,7 @@
#include "chrome/common/process_watcher.h"
#include "AppProcessPermissions.h"
#include "AppProcessChecker.h"
#include "AudioChannelService.h"
#include "CrashReporterParent.h"
#include "IHistory.h"
@ -712,8 +712,17 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
CrashReporterParent* crashReporter =
static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
NS_ConvertUTF16toUTF8(mAppManifestURL));
// If we're an app process, always stomp the latest URI
// loaded in the child process with our manifest URL. We
// would rather associate the crashes with apps than
// random child windows loaded in them.
//
// XXX would be nice if we could get both ...
if (!mAppManifestURL.IsEmpty()) {
crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
NS_ConvertUTF16toUTF8(mAppManifestURL));
}
crashReporter->GenerateCrashReport(this, NULL);
nsAutoString dumpID(crashReporter->ChildDumpID());
@ -2147,6 +2156,11 @@ ContentParent::CheckPermission(const nsAString& aPermission)
return AssertAppProcessPermission(this, NS_ConvertUTF16toUTF8(aPermission).get());
}
bool
ContentParent::CheckManifestURL(const nsAString& aManifestURL)
{
return AssertAppProcessManifestURL(this, NS_ConvertUTF16toUTF8(aManifestURL).get());
}
} // namespace dom
} // namespace mozilla

View File

@ -102,6 +102,7 @@ public:
virtual bool DoSendAsyncMessage(const nsAString& aMessage,
const mozilla::dom::StructuredCloneData& aData);
virtual bool CheckPermission(const nsAString& aPermission);
virtual bool CheckManifestURL(const nsAString& aManifestURL);
/** Notify that a tab was destroyed during normal operation. */
void NotifyTabDestroyed(PBrowserParent* aTab);

View File

@ -31,7 +31,7 @@ EXPORTS_NAMESPACES = \
$(NULL)
EXPORTS_mozilla = \
AppProcessPermissions.h \
AppProcessChecker.h \
$(NULL)
EXPORTS_mozilla/dom = \
@ -55,7 +55,7 @@ EXPORTS_mozilla/dom/ipc = \
$(NULL)
CPPSRCS = \
AppProcessPermissions.cpp \
AppProcessChecker.cpp \
Blob.cpp \
ContentProcess.cpp \
ContentParent.cpp \

View File

@ -30,6 +30,7 @@
#include "nsContentUtils.h"
#include "nsEmbedCID.h"
#include "nsEventListenerManager.h"
#include "nsExceptionHandler.h"
#include "mozilla/dom/Element.h"
#include "nsIAppsService.h"
#include "nsIBaseWindow.h"
@ -1089,6 +1090,10 @@ TabChild::RecvLoadURL(const nsCString& uri)
NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
}
#ifdef MOZ_CRASHREPORTER
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), uri);
#endif
return true;
}

View File

@ -168,6 +168,20 @@ SystemMessageInternal.prototype = {
receiveMessage: function receiveMessage(aMessage) {
let msg = aMessage.json;
// To prevent the hacked child process from sending commands to parent
// to manage system messages, we need to check its manifest URL.
if (["SystemMessageManager:Register",
"SystemMessageManager:Unregister",
"SystemMessageManager:GetPendingMessages",
"SystemMessageManager:HasPendingMessages",
"SystemMessageManager:Message:Return:OK"].indexOf(aMessage.name) != -1) {
if (!aMessage.target.assertContainApp(msg.manifest)) {
debug("Got message from a child process containing illegal manifest URL.");
return null;
}
}
switch(aMessage.name) {
case "SystemMessageManager:AskReadyToRegister":
return true;

View File

@ -8,7 +8,7 @@
#include "nsJSUtils.h"
#include "nsIDOMTCPSocket.h"
#include "mozilla/unused.h"
#include "mozilla/AppProcessPermissions.h"
#include "mozilla/AppProcessChecker.h"
namespace IPC {

View File

@ -4,7 +4,7 @@
"use strict";
const DEBUG = true;
const DEBUG = false;
function debug(s) {
if (DEBUG) dump("-*- SettingsManager: " + s + "\n");
}

View File

@ -42,7 +42,7 @@ function test() {
HTML_TAG("dfn", "Span")
HTML_TAG("dir", "Shared")
HTML_TAG("div", "Div")
HTML_TAG("dl", "SharedList")
HTML_TAG("dl", "DList")
HTML_TAG("dt", "Span")
HTML_TAG("em", "Span")
HTML_TAG("embed", "SharedObject")
@ -84,7 +84,7 @@ function test() {
HTML_TAG("noframes", "Div")
HTML_TAG("noscript", "Div")
HTML_TAG("object", "Object")
HTML_TAG("ol", "SharedList")
HTML_TAG("ol", "OList")
HTML_TAG("optgroup", "OptGroup")
HTML_TAG("option", "Option")
HTML_TAG("p", "Paragraph")
@ -115,7 +115,7 @@ function test() {
HTML_TAG("tr", "TableRow")
HTML_TAG("tt", "Span")
HTML_TAG("u", "Span")
HTML_TAG("ul", "SharedList")
HTML_TAG("ul", "UList")
HTML_TAG("var", "Span")
HTML_TAG("wbr", "Shared")
HTML_TAG("xmp", "Span")

View File

@ -60,7 +60,7 @@ HTML_TAG("del", "Mod")
HTML_TAG("dfn", "Span")
HTML_TAG("dir", "Shared")
HTML_TAG("div", "Div")
HTML_TAG("dl", "SharedList")
HTML_TAG("dl", "DList")
HTML_TAG("dt", "Span")
HTML_TAG("em", "Span")
HTML_TAG("embed", "SharedObject")
@ -102,7 +102,7 @@ HTML_TAG("noembed", "Div")
HTML_TAG("noframes", "Div")
HTML_TAG("noscript", "Div")
HTML_TAG("object", "Object")
HTML_TAG("ol", "SharedList")
HTML_TAG("ol", "OList")
HTML_TAG("optgroup", "OptGroup")
HTML_TAG("option", "Option")
HTML_TAG("p", "Paragraph")
@ -133,7 +133,7 @@ HTML_TAG("title", "Title")
HTML_TAG("tr", "TableRow")
HTML_TAG("tt", "Span")
HTML_TAG("u", "Span")
HTML_TAG("ul", "SharedList")
HTML_TAG("ul", "UList")
HTML_TAG("var", "Span")
HTML_TAG("wbr", "Shared")
HTML_TAG("xmp", "Span")

View File

@ -5,7 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Hal.h"
#include "mozilla/AppProcessPermissions.h"
#include "mozilla/AppProcessChecker.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/hal_sandbox/PHalChild.h"
#include "mozilla/hal_sandbox/PHalParent.h"

View File

@ -282,12 +282,56 @@ File(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
static JSBool
Blob(JSContext *cx, unsigned argc, jsval *vp)
{
nsresult rv;
nsCOMPtr<nsISupports> native;
rv = nsDOMMultipartFile::NewBlob(getter_AddRefs(native));
if (NS_FAILED(rv)) {
XPCThrower::Throw(rv, cx);
return false;
}
nsCOMPtr<nsIJSNativeInitializer> initializer = do_QueryInterface(native);
NS_ASSERTION(initializer, "what?");
rv = initializer->Initialize(nullptr, cx, nullptr, argc, JS_ARGV(cx, vp));
if (NS_FAILED(rv)) {
XPCThrower::Throw(rv, cx);
return false;
}
nsXPConnect* xpc = nsXPConnect::GetXPConnect();
if (!xpc) {
XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
return false;
}
JSObject* glob = JS_GetGlobalForScopeChain(cx);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
jsval retval;
rv = xpc->WrapNativeToJSVal(cx, glob, native, nullptr,
&NS_GET_IID(nsISupports),
true, &retval, nullptr);
if (NS_FAILED(rv)) {
XPCThrower::Throw(rv, cx);
return false;
}
JS_SET_RVAL(cx, vp, retval);
return true;
}
static JSFunctionSpec gGlobalFun[] = {
JS_FS("dump", Dump, 1,0),
JS_FS("debug", Debug, 1,0),
JS_FS("atob", Atob, 1,0),
JS_FS("btoa", Btoa, 1,0),
JS_FS("File", File, 1,JSFUN_CONSTRUCTOR),
JS_FS("Blob", Blob, 2,JSFUN_CONSTRUCTOR),
JS_FS_END
};

View File

@ -0,0 +1,85 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
function do_check_true(cond, text) {
// we don't have the test harness' utilities in this scope, so we need this
// little helper. In the failure case, the exception is propagated to the
// caller in the main run_test() function, and the test fails.
if (!cond)
throw "Failed check: " + text;
}
function BlobComponent() {
this.wrappedJSObject = this;
}
BlobComponent.prototype =
{
doTest: function() {
// throw if anything goes wrong
let testContent = "<a id=\"a\"><b id=\"b\">hey!<\/b><\/a>";
// should be able to construct a file
var f1 = Blob([testContent], {"type" : "text/xml"});
// with either constructor syntax
var f2 = new Blob([testContent], {"type" : "text/xml"});
// do some tests
do_check_true(f1 instanceof Ci.nsIDOMBlob, "Should be a DOM Blob");
do_check_true(f2 instanceof Ci.nsIDOMBlob, "Should be a DOM Blob");
do_check_true(!(f1 instanceof Ci.nsIDOMFile), "Should not be a DOM File");
do_check_true(!(f2 instanceof Ci.nsIDOMFile), "Should not be a DOM File");
do_check_true(f1.type == "text/xml", "Wrong type");
do_check_true(f2.type == "text/xml", "Wrong type");
do_check_true(f1.size == testContent.length, "Wrong content size");
do_check_true(f2.size == testContent.length, "Wrong content size");
var f3 = new Blob();
do_check_true(f3.size == 0, "Wrong size");
do_check_true(f3.type == "", "Wrong type");
var threw = false;
try {
// Needs a valid ctor argument
var f3 = Blob(Date(132131532));
} catch (e) {
threw = true;
}
do_check_true(threw, "Passing a random object should fail");
return true;
},
// nsIClassInfo + information for XPCOM registration code in XPCOMUtils.jsm
classDescription: "Blob in components scope code",
classID: Components.ID("{06215993-a3c2-41e3-bdfd-0a3a2cc0b65c}"),
contractID: "@mozilla.org/tests/component-blob;1",
// nsIClassInfo
implementationLanguage: Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,
flags: 0,
getInterfaces: function getInterfaces(aCount) {
var interfaces = [Components.interfaces.nsIClassInfo];
aCount.value = interfaces.length;
return interfaces;
},
getHelperForLanguage: function getHelperForLanguage(aLanguage) {
return null;
},
// nsISupports
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIClassInfo])
};
var gComponentsArray = [BlobComponent];
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(gComponentsArray);

View File

@ -0,0 +1,2 @@
component {06215993-a3c2-41e3-bdfd-0a3a2cc0b65c} component-blob.js
contract @mozilla.org/tests/component-blob;1 {06215993-a3c2-41e3-bdfd-0a3a2cc0b65c}

View File

@ -0,0 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
function run_test() {
do_load_manifest("component-blob.manifest");
const contractID = "@mozilla.org/tests/component-blob;1";
do_check_true(contractID in Components.classes);
var foo = Components.classes[contractID]
.createInstance(Components.interfaces.nsIClassInfo);
do_check_true(Boolean(foo));
do_check_true(foo.contractID == contractID);
do_check_true(!!foo.wrappedJSObject);
do_check_true(foo.wrappedJSObject.doTest());
}

View File

@ -15,6 +15,7 @@ tail =
[test_bug780370.js]
[test_bug_442086.js]
[test_file.js]
[test_blob.js]
[test_import.js]
[test_import_fail.js]
[test_js_weak_references.js]

View File

@ -109,6 +109,10 @@ class B2GOptions(ReftestOptions):
type="string", dest="logcat_dir",
help="directory to store logcat dump files")
defaults["logcat_dir"] = None
self.add_option('--busybox', action='store',
type='string', dest='busybox',
help="Path to busybox binary to install on device")
defaults['busybox'] = None
defaults["remoteTestRoot"] = "/data/local/tests"
defaults["logFile"] = "reftest.log"
defaults["autorun"] = True
@ -484,6 +488,8 @@ def main(args=sys.argv[1:]):
kwargs['gecko_path'] = options.geckoPath
if options.logcat_dir:
kwargs['logcat_dir'] = options.logcat_dir
if options.busybox:
kwargs['busybox'] = options.busybox
if options.emulator_res:
kwargs['emulator_res'] = options.emulator_res
if options.b2gPath:

View File

@ -70,7 +70,7 @@ HTML_TAG(del, Mod)
HTML_HTMLELEMENT_TAG(dfn)
HTML_TAG(dir, Shared)
HTML_TAG(div, Div)
HTML_TAG(dl, SharedList)
HTML_TAG(dl, DList)
HTML_HTMLELEMENT_TAG(dt)
HTML_HTMLELEMENT_TAG(em)
HTML_TAG(embed, SharedObject)
@ -120,7 +120,7 @@ HTML_HTMLELEMENT_TAG(noembed)
HTML_HTMLELEMENT_TAG(noframes)
HTML_HTMLELEMENT_TAG(noscript)
HTML_TAG(object, Object)
HTML_TAG(ol, SharedList)
HTML_TAG(ol, OList)
HTML_TAG(optgroup, OptGroup)
HTML_TAG(option, Option)
HTML_TAG(output, Output)
@ -156,7 +156,7 @@ HTML_TAG(title, Title)
HTML_TAG(tr, TableRow)
HTML_HTMLELEMENT_TAG(tt)
HTML_HTMLELEMENT_TAG(u)
HTML_TAG(ul, SharedList)
HTML_TAG(ul, UList)
HTML_HTMLELEMENT_TAG(var)
#if defined(MOZ_MEDIA)
HTML_TAG(video, Video)

View File

@ -102,6 +102,10 @@ class B2GOptions(MochitestOptions):
type="string", dest="logcat_dir",
help="directory to store logcat dump files")
defaults["logcat_dir"] = None
self.add_option('--busybox', action='store',
type='string', dest='busybox',
help="Path to busybox binary to install on device")
defaults['busybox'] = None
defaults["remoteTestRoot"] = "/data/local/tests"
defaults["logFile"] = "mochitest.log"
@ -482,6 +486,8 @@ def main():
kwargs['gecko_path'] = options.geckoPath
if options.logcat_dir:
kwargs['logcat_dir'] = options.logcat_dir
if options.busybox:
kwargs['busybox'] = options.busybox
# needless to say sdcard is only valid if using an emulator
if options.sdcard:
kwargs['sdcard'] = options.sdcard

View File

@ -13,6 +13,9 @@
#include "nscore.h"
#include "nsTextStore.h"
#include "nsWindow.h"
#ifdef MOZ_METRO
#include "winrt/MetroWidget.h"
#endif
#include "nsPrintfCString.h"
#include "WinUtils.h"
#include "mozilla/Preferences.h"
@ -339,7 +342,6 @@ nsTextStore::nsTextStore()
mRefCnt = 1;
mEditCookie = 0;
mSinkMask = 0;
mWindow = nullptr;
mLock = 0;
mLockQueued = 0;
mTextChange.acpStart = INT32_MAX;
@ -351,8 +353,8 @@ nsTextStore::~nsTextStore()
{
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore instance is destroyed, "
"mWindow=0x%p, mDocumentMgr=0x%p, mContext=0x%p",
this, mWindow, mDocumentMgr.get(), mContext.get()));
"mWidget=0x%p, mDocumentMgr=0x%p, mContext=0x%p",
this, mWidget, mDocumentMgr, mContext));
if (mCompositionTimer) {
mCompositionTimer->Cancel();
@ -362,12 +364,12 @@ nsTextStore::~nsTextStore()
}
bool
nsTextStore::Create(nsWindow* aWindow,
nsTextStore::Create(nsWindowBase* aWidget,
IMEState::Enabled aIMEEnabled)
{
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::Create(aWindow=0x%p, aIMEEnabled=%s)",
this, aWindow, GetIMEEnabledName(aIMEEnabled)));
("TSF: 0x%p nsTextStore::Create(aWidget=0x%p, aIMEEnabled=%s)",
this, aWidget, GetIMEEnabledName(aIMEEnabled)));
if (mDocumentMgr) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
@ -385,7 +387,8 @@ nsTextStore::Create(nsWindow* aWindow,
"(0x%08X)", this, hr));
return false;
}
mWindow = aWindow;
mWidget = aWidget;
// Create context and add it to document manager
hr = mDocumentMgr->CreateContext(sTsfClientId, 0,
static_cast<ITextStoreACP*>(this),
@ -425,13 +428,13 @@ nsTextStore::Destroy(void)
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::Destroy()", this));
if (mWindow) {
if (mWidget) {
// When blurred, Tablet Input Panel posts "blur" messages
// and try to insert text when the message is retrieved later.
// But by that time the text store is already destroyed,
// so try to get the message early
MSG msg;
if (::PeekMessageW(&msg, mWindow->GetWindowHandle(),
if (::PeekMessageW(&msg, mWidget->GetWindowHandle(),
sFlushTIPInputMessage, sFlushTIPInputMessage,
PM_REMOVE)) {
::DispatchMessageW(&msg);
@ -443,7 +446,7 @@ nsTextStore::Destroy(void)
mDocumentMgr = NULL;
}
mSink = NULL;
mWindow = NULL;
mWidget = nullptr;
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::Destroy() succeeded", this));
@ -756,9 +759,9 @@ nsTextStore::GetSelectionInternal(TS_SELECTION_ACP &aSelectionACP)
"try to get normal selection...", this));
// Construct and initialize an event to get selection info
nsQueryContentEvent event(true, NS_QUERY_SELECTED_TEXT, mWindow);
mWindow->InitEvent(event);
mWindow->DispatchWindowEvent(&event);
nsQueryContentEvent event(true, NS_QUERY_SELECTED_TEXT, mWidget);
mWidget->InitEvent(event);
mWidget->DispatchWindowEvent(&event);
if (!event.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetSelectionInternal() FAILED to "
@ -1087,8 +1090,8 @@ nsTextStore::SendTextEventForCompositionString()
}
// Use NS_TEXT_TEXT to set composition string
nsTextEvent event(true, NS_TEXT_TEXT, mWindow);
mWindow->InitEvent(event);
nsTextEvent event(true, NS_TEXT_TEXT, mWidget);
mWidget->InitEvent(event);
nsRefPtr<ITfRange> composingRange;
hr = mCompositionView->GetRange(getter_AddRefs(composingRange));
@ -1218,18 +1221,18 @@ nsTextStore::SendTextEventForCompositionString()
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() "
"dispatching compositionupdate event...", this));
nsCompositionEvent compositionUpdate(true, NS_COMPOSITION_UPDATE,
mWindow);
mWindow->InitEvent(compositionUpdate);
mWidget);
mWidget->InitEvent(compositionUpdate);
compositionUpdate.data = mCompositionString;
mLastDispatchedCompositionString = mCompositionString;
mWindow->DispatchWindowEvent(&compositionUpdate);
mWidget->DispatchWindowEvent(&compositionUpdate);
}
if (mWindow && !mWindow->Destroyed()) {
if (mWidget && !mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() "
"dispatching text event...", this));
mWindow->DispatchWindowEvent(&event);
mWidget->DispatchWindowEvent(&event);
}
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
@ -1282,12 +1285,12 @@ nsTextStore::SetSelectionInternal(const TS_SELECTION_ACP* pSelection,
}
return S_OK;
} else {
nsSelectionEvent event(true, NS_SELECTION_SET, mWindow);
nsSelectionEvent event(true, NS_SELECTION_SET, mWidget);
event.mOffset = pSelection->acpStart;
event.mLength = uint32_t(pSelection->acpEnd - pSelection->acpStart);
event.mReversed = pSelection->style.ase == TS_AE_START;
mWindow->InitEvent(event);
mWindow->DispatchWindowEvent(&event);
mWidget->InitEvent(event);
mWidget->DispatchWindowEvent(&event);
if (!event.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::SetSelectionInternal() FAILED due to "
@ -1415,10 +1418,10 @@ nsTextStore::GetText(LONG acpStart,
}
}
// Send NS_QUERY_TEXT_CONTENT to get text content
nsQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, mWindow);
mWindow->InitEvent(event);
nsQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, mWidget);
mWidget->InitEvent(event);
event.InitForQueryTextContent(uint32_t(acpStart), length);
mWindow->DispatchWindowEvent(&event);
mWidget->DispatchWindowEvent(&event);
if (!event.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetText() FAILED due to "
@ -1693,11 +1696,11 @@ nsTextStore::GetEndACP(LONG *pacp)
}
// Flattened text is retrieved and its length returned
nsQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, mWindow);
mWindow->InitEvent(event);
nsQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, mWidget);
mWidget->InitEvent(event);
// Return entire text
event.InitForQueryTextContent(0, INT32_MAX);
mWindow->DispatchWindowEvent(&event);
mWidget->DispatchWindowEvent(&event);
if (!event.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetEndACP() FAILED due to "
@ -1801,10 +1804,10 @@ nsTextStore::GetTextExt(TsViewCookie vcView,
}
// use NS_QUERY_TEXT_RECT to get rect in system, screen coordinates
nsQueryContentEvent event(true, NS_QUERY_TEXT_RECT, mWindow);
mWindow->InitEvent(event);
nsQueryContentEvent event(true, NS_QUERY_TEXT_RECT, mWidget);
mWidget->InitEvent(event);
event.InitForQueryTextRect(acpStart, acpEnd - acpStart);
mWindow->DispatchWindowEvent(&event);
mWidget->DispatchWindowEvent(&event);
if (!event.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetTextExt() FAILED due to "
@ -1817,19 +1820,21 @@ nsTextStore::GetTextExt(TsViewCookie vcView,
if (event.mReply.mRect.height <= 0)
event.mReply.mRect.height = 1;
// convert to unclipped screen rect
nsWindow* refWindow = static_cast<nsWindow*>(
event.mReply.mFocusedWidget ? event.mReply.mFocusedWidget : mWindow);
// Result rect is in top level widget coordinates
refWindow = refWindow->GetTopLevelWindow(false);
if (!refWindow) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetTextExt() FAILED due to "
"no top level window", this));
return E_FAIL;
}
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
// convert to unclipped screen rect
nsWindow* refWindow = static_cast<nsWindow*>(
event.mReply.mFocusedWidget ? event.mReply.mFocusedWidget : mWidget);
// Result rect is in top level widget coordinates
refWindow = refWindow->GetTopLevelWindow(false);
if (!refWindow) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetTextExt() FAILED due to "
"no top level window", this));
return E_FAIL;
}
event.mReply.mRect.MoveBy(refWindow->WidgetToScreenOffset());
event.mReply.mRect.MoveBy(refWindow->WidgetToScreenOffset());
}
// get bounding screen rect to test for clipping
if (!GetScreenExtInternal(*prc)) {
@ -1902,9 +1907,9 @@ nsTextStore::GetScreenExtInternal(RECT &aScreenExt)
("TSF: 0x%p nsTextStore::GetScreenExtInternal()", this));
// use NS_QUERY_EDITOR_RECT to get rect in system, screen coordinates
nsQueryContentEvent event(true, NS_QUERY_EDITOR_RECT, mWindow);
mWindow->InitEvent(event);
mWindow->DispatchWindowEvent(&event);
nsQueryContentEvent event(true, NS_QUERY_EDITOR_RECT, mWidget);
mWidget->InitEvent(event);
mWidget->DispatchWindowEvent(&event);
if (!event.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetScreenExtInternal() FAILED due to "
@ -1912,35 +1917,50 @@ nsTextStore::GetScreenExtInternal(RECT &aScreenExt)
return false;
}
nsWindow* refWindow = static_cast<nsWindow*>(
event.mReply.mFocusedWidget ? event.mReply.mFocusedWidget : mWindow);
// Result rect is in top level widget coordinates
refWindow = refWindow->GetTopLevelWindow(false);
if (!refWindow) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetScreenExtInternal() FAILED due to "
"no top level window", this));
return false;
}
nsIntRect boundRect;
if (NS_FAILED(refWindow->GetClientBounds(boundRect))) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetScreenExtInternal() FAILED due to "
"failed to get the client bounds", this));
return false;
}
boundRect.MoveTo(0, 0);
// Clip frame rect to window rect
boundRect.IntersectRect(event.mReply.mRect, boundRect);
if (!boundRect.IsEmpty()) {
boundRect.MoveBy(refWindow->WidgetToScreenOffset());
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro) {
nsIntRect boundRect;
if (NS_FAILED(mWidget->GetClientBounds(boundRect))) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetScreenExtInternal() FAILED due to "
"failed to get the client bounds", this));
return false;
}
::SetRect(&aScreenExt, boundRect.x, boundRect.y,
boundRect.XMost(), boundRect.YMost());
} else {
::SetRectEmpty(&aScreenExt);
NS_ASSERTION(XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop,
"environment isn't WindowsEnvironmentType_Desktop!");
nsWindow* refWindow = static_cast<nsWindow*>(
event.mReply.mFocusedWidget ?
event.mReply.mFocusedWidget : mWidget);
// Result rect is in top level widget coordinates
refWindow = refWindow->GetTopLevelWindow(false);
if (!refWindow) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetScreenExtInternal() FAILED due to "
"no top level window", this));
return false;
}
nsIntRect boundRect;
if (NS_FAILED(refWindow->GetClientBounds(boundRect))) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::GetScreenExtInternal() FAILED due to "
"failed to get the client bounds", this));
return false;
}
boundRect.MoveTo(0, 0);
// Clip frame rect to window rect
boundRect.IntersectRect(event.mReply.mRect, boundRect);
if (!boundRect.IsEmpty()) {
boundRect.MoveBy(refWindow->WidgetToScreenOffset());
::SetRect(&aScreenExt, boundRect.x, boundRect.y,
boundRect.XMost(), boundRect.YMost());
} else {
::SetRectEmpty(&aScreenExt);
}
}
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
@ -1956,8 +1976,9 @@ nsTextStore::GetWnd(TsViewCookie vcView,
HWND *phwnd)
{
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::GetWnd(vcView=%ld, phwnd=0x%p), mWindow=0x%p",
this, vcView, phwnd, mWindow));
("TSF: 0x%p nsTextStore::GetWnd(vcView=%ld, phwnd=0x%p), "
"mWidget=0x%p",
this, vcView, phwnd, mWidget));
if (vcView != TEXTSTORE_DEFAULT_VIEW) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
@ -1973,7 +1994,7 @@ nsTextStore::GetWnd(TsViewCookie vcView,
return E_INVALIDARG;
}
*phwnd = mWindow->GetWindowHandle();
*phwnd = mWidget->GetWindowHandle();
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::GetWnd() succeeded: *phwnd=0x%p",
@ -2135,10 +2156,11 @@ nsTextStore::InsertTextAtSelectionInternal(const nsAString &aInsertStr,
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() "
"dispatching a compositionstart event...", this));
nsCompositionEvent compStartEvent(true, NS_COMPOSITION_START, mWindow);
mWindow->InitEvent(compStartEvent);
mWindow->DispatchWindowEvent(&compStartEvent);
if (!mWindow || mWindow->Destroyed()) {
nsCompositionEvent compStartEvent(true, NS_COMPOSITION_START,
mWidget);
mWidget->InitEvent(compStartEvent);
mWidget->DispatchWindowEvent(&compStartEvent);
if (!mWidget || mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() FAILED "
"due to the widget destroyed by compositionstart event", this));
@ -2149,10 +2171,11 @@ nsTextStore::InsertTextAtSelectionInternal(const nsAString &aInsertStr,
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() "
"dispatching a compositionupdate event...", this));
nsCompositionEvent compUpdateEvent(true, NS_COMPOSITION_UPDATE, mWindow);
nsCompositionEvent compUpdateEvent(true, NS_COMPOSITION_UPDATE,
mWidget);
compUpdateEvent.data = aInsertStr;
mWindow->DispatchWindowEvent(&compUpdateEvent);
if (!mWindow || mWindow->Destroyed()) {
mWidget->DispatchWindowEvent(&compUpdateEvent);
if (!mWidget || mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() "
"FAILED due to the widget destroyed by compositionupdate event",
@ -2164,13 +2187,13 @@ nsTextStore::InsertTextAtSelectionInternal(const nsAString &aInsertStr,
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() "
"dispatching a text event...", this));
nsTextEvent textEvent(true, NS_TEXT_TEXT, mWindow);
mWindow->InitEvent(textEvent);
nsTextEvent textEvent(true, NS_TEXT_TEXT, mWidget);
mWidget->InitEvent(textEvent);
textEvent.theText = aInsertStr;
textEvent.theText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
NS_LITERAL_STRING("\n"));
mWindow->DispatchWindowEvent(&textEvent);
if (!mWindow || mWindow->Destroyed()) {
mWidget->DispatchWindowEvent(&textEvent);
if (!mWidget || mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() FAILED "
"due to the widget destroyed by text event", this));
@ -2180,10 +2203,10 @@ nsTextStore::InsertTextAtSelectionInternal(const nsAString &aInsertStr,
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() "
"dispatching a compositionend event...", this));
nsCompositionEvent compEndEvent(true, NS_COMPOSITION_END, mWindow);
nsCompositionEvent compEndEvent(true, NS_COMPOSITION_END, mWidget);
compEndEvent.data = aInsertStr;
mWindow->DispatchWindowEvent(&compEndEvent);
if (!mWindow || mWindow->Destroyed()) {
mWidget->DispatchWindowEvent(&compEndEvent);
if (!mWidget || mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() FAILED "
"due to the widget destroyed by compositionend event", this));
@ -2209,9 +2232,9 @@ nsTextStore::InsertTextAtSelectionInternal(const nsAString &aInsertStr,
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() succeeded: "
"mWindow=0x%p, mWindow->Destroyed()=%s, aTextChange={ acpStart=%ld, "
"mWidget=0x%p, mWidget->Destroyed()=%s, aTextChange={ acpStart=%ld, "
"acpOldEnd=%ld, acpNewEnd=%ld }",
this, mWindow, GetBoolName(mWindow ? mWindow->Destroyed() : true),
this, mWidget, GetBoolName(mWidget ? mWidget->Destroyed() : true),
aTextChange ? aTextChange->acpStart : 0,
aTextChange ? aTextChange->acpOldEnd : 0,
aTextChange ? aTextChange->acpNewEnd : 0));
@ -2264,12 +2287,12 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
"dispatching selectionset event..."));
// Select composition range so the new composition replaces the range
nsSelectionEvent selEvent(true, NS_SELECTION_SET, mWindow);
mWindow->InitEvent(selEvent);
nsSelectionEvent selEvent(true, NS_SELECTION_SET, mWidget);
mWidget->InitEvent(selEvent);
selEvent.mOffset = uint32_t(mCompositionStart);
selEvent.mLength = uint32_t(mCompositionLength);
selEvent.mReversed = false;
mWindow->DispatchWindowEvent(&selEvent);
mWidget->DispatchWindowEvent(&selEvent);
if (!selEvent.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::OnStartCompositionInternal() FAILED due "
@ -2278,9 +2301,9 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
}
// Set up composition
nsQueryContentEvent queryEvent(true, NS_QUERY_SELECTED_TEXT, mWindow);
mWindow->InitEvent(queryEvent);
mWindow->DispatchWindowEvent(&queryEvent);
nsQueryContentEvent queryEvent(true, NS_QUERY_SELECTED_TEXT, mWidget);
mWidget->InitEvent(queryEvent);
mWidget->DispatchWindowEvent(&queryEvent);
if (!queryEvent.mSucceeded) {
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
("TSF: 0x%p nsTextStore::OnStartCompositionInternal() FAILED due "
@ -2299,9 +2322,9 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
mCompositionSelection.style.ase = TS_AE_END;
mCompositionSelection.style.fInterimChar = FALSE;
}
nsCompositionEvent event(true, NS_COMPOSITION_START, mWindow);
mWindow->InitEvent(event);
mWindow->DispatchWindowEvent(&event);
nsCompositionEvent event(true, NS_COMPOSITION_START, mWidget);
mWidget->InitEvent(event);
mWidget->DispatchWindowEvent(&event);
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: 0x%p nsTextStore::OnStartCompositionInternal() succeeded: "
@ -2476,12 +2499,12 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
("TSF: 0x%p nsTextStore::OnEndComposition(), "
"dispatching compositionupdate event...", this));
nsCompositionEvent compositionUpdate(true, NS_COMPOSITION_UPDATE,
mWindow);
mWindow->InitEvent(compositionUpdate);
mWidget);
mWidget->InitEvent(compositionUpdate);
compositionUpdate.data = mCompositionString;
mLastDispatchedCompositionString = mCompositionString;
mWindow->DispatchWindowEvent(&compositionUpdate);
if (!mWindow || mWindow->Destroyed()) {
mWidget->DispatchWindowEvent(&compositionUpdate);
if (!mWidget || mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::OnEndComposition(), "
"succeeded, but the widget has gone", this));
@ -2494,14 +2517,14 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
"dispatching text event...", this));
// Use NS_TEXT_TEXT to commit composition string
nsTextEvent textEvent(true, NS_TEXT_TEXT, mWindow);
mWindow->InitEvent(textEvent);
nsTextEvent textEvent(true, NS_TEXT_TEXT, mWidget);
mWidget->InitEvent(textEvent);
textEvent.theText = mCompositionString;
textEvent.theText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
NS_LITERAL_STRING("\n"));
mWindow->DispatchWindowEvent(&textEvent);
mWidget->DispatchWindowEvent(&textEvent);
if (!mWindow || mWindow->Destroyed()) {
if (!mWidget || mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::OnEndComposition(), "
"succeeded, but the widget has gone", this));
@ -2512,12 +2535,12 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
("TSF: 0x%p nsTextStore::OnEndComposition(), "
"dispatching compositionend event...", this));
nsCompositionEvent event(true, NS_COMPOSITION_END, mWindow);
nsCompositionEvent event(true, NS_COMPOSITION_END, mWidget);
event.data = mLastDispatchedCompositionString;
mWindow->InitEvent(event);
mWindow->DispatchWindowEvent(&event);
mWidget->InitEvent(event);
mWidget->DispatchWindowEvent(&event);
if (!mWindow || mWindow->Destroyed()) {
if (!mWidget || mWidget->Destroyed()) {
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
("TSF: 0x%p nsTextStore::OnEndComposition(), "
"succeeded, but the widget has gone", this));
@ -2538,22 +2561,24 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
// static
nsresult
nsTextStore::OnFocusChange(bool aFocus,
nsWindow* aWindow,
nsTextStore::OnFocusChange(bool aGotFocus,
nsWindowBase* aFocusedWidget,
IMEState::Enabled aIMEEnabled)
{
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
("TSF: nsTextStore::OnFocusChange(aFocus=%s, aWindow=0x%p, "
"aIMEEnabled=%s), sTsfThreadMgr=0x%p, sTsfTextStore=0x%p",
GetBoolName(aFocus), aWindow, GetIMEEnabledName(aIMEEnabled),
sTsfThreadMgr, sTsfTextStore));
("TSF: nsTextStore::OnFocusChange(aGotFocus=%s, "
"aFocusedWidget=0x%p, aIMEEnabled=%s), sTsfThreadMgr=0x%p, "
"sTsfTextStore=0x%p",
GetBoolName(aGotFocus), aFocusedWidget,
GetIMEEnabledName(aIMEEnabled), sTsfThreadMgr, sTsfTextStore));
// no change notifications if TSF is disabled
if (!sTsfThreadMgr || !sTsfTextStore)
if (!sTsfThreadMgr || !sTsfTextStore) {
return NS_ERROR_NOT_AVAILABLE;
}
if (aFocus) {
bool bRet = sTsfTextStore->Create(aWindow, aIMEEnabled);
if (aGotFocus) {
bool bRet = sTsfTextStore->Create(aFocusedWidget, aIMEEnabled);
NS_ENSURE_TRUE(bRet, NS_ERROR_FAILURE);
NS_ENSURE_TRUE(sTsfTextStore->mDocumentMgr, NS_ERROR_FAILURE);
HRESULT hr = sTsfThreadMgr->SetFocus(sTsfTextStore->mDocumentMgr);
@ -2594,7 +2619,7 @@ nsTextStore::OnTextChangeInternal(uint32_t aStart,
mTextChange.acpStart = NS_MIN(mTextChange.acpStart, LONG(aStart));
mTextChange.acpOldEnd = NS_MAX(mTextChange.acpOldEnd, LONG(aOldEnd));
mTextChange.acpNewEnd = NS_MAX(mTextChange.acpNewEnd, LONG(aNewEnd));
::PostMessageW(mWindow->GetWindowHandle(),
::PostMessageW(mWidget->GetWindowHandle(),
WM_USER_TSF_TEXTCHANGE, 0, 0);
}
return NS_OK;

View File

@ -11,6 +11,7 @@
#include "nsCOMPtr.h"
#include "nsITimer.h"
#include "nsIWidget.h"
#include "nsWindowBase.h"
#include "mozilla/Attributes.h"
#include <msctf.h>
@ -22,6 +23,9 @@ struct ITfDisplayAttributeMgr;
struct ITfCategoryMgr;
class nsWindow;
class nsTextEvent;
#ifdef MOZ_METRO
class MetroWidget;
#endif
// It doesn't work well when we notify TSF of text change
// during a mutation observer call because things get broken.
@ -100,8 +104,9 @@ public:
sTsfTextStore->SetInputContextInternal(aContext.mIMEState.mEnabled);
}
static nsresult OnFocusChange(bool, nsWindow*, IMEState::Enabled);
static nsresult OnFocusChange(bool aGotFocus,
nsWindowBase* aFocusedWidget,
IMEState::Enabled aIMEEnabled);
static nsresult OnTextChange(uint32_t aStart,
uint32_t aOldEnd,
uint32_t aNewEnd)
@ -154,7 +159,8 @@ protected:
nsTextStore();
~nsTextStore();
bool Create(nsWindow*, IMEState::Enabled);
bool Create(nsWindowBase* aWidget,
IMEState::Enabled aIMEEnabled);
bool Destroy(void);
bool IsReadLock(DWORD aLock) const
@ -192,6 +198,8 @@ protected:
HRESULT SaveTextEvent(const nsTextEvent* aEvent);
nsresult OnCompositionTimer();
// Holds the pointer to our current win32 or metro widget
nsRefPtr<nsWindowBase> mWidget;
// Document manager for the currently focused editor
nsRefPtr<ITfDocumentMgr> mDocumentMgr;
// Edit cookie associated with the current editing context
@ -202,8 +210,6 @@ protected:
nsRefPtr<ITextStoreACPSink> mSink;
// TS_AS_* mask of what events to notify
DWORD mSinkMask;
// Window containing the focused editor
nsWindow* mWindow;
// 0 if not locked, otherwise TS_LF_* indicating the current lock
DWORD mLock;
// 0 if no lock is queued, otherwise TS_LF_* indicating the queue lock

View File

@ -302,7 +302,7 @@ static const int32_t kResizableBorderMinSize = 3;
*
**************************************************************/
nsWindow::nsWindow() : nsBaseWidget()
nsWindow::nsWindow() : nsWindowBase()
{
#ifdef PR_LOGGING
if (!gWindowsLog) {
@ -5046,7 +5046,9 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
case WM_APPCOMMAND:
{
uint32_t appCommand = GET_APPCOMMAND_LPARAM(lParam);
uint32_t contentCommandMessage = NS_EVENT_NULL;
// XXX After we implement KeyboardEvent.key, we should dispatch the
// key event if (GET_DEVICE_LPARAM(lParam) == FAPPCOMMAND_KEY) is.
switch (appCommand)
{
case APPCOMMAND_BROWSER_BACKWARD:
@ -5075,6 +5077,31 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam,
result = true;
}
break;
// Use content command for following commands:
case APPCOMMAND_COPY:
contentCommandMessage = NS_CONTENT_COMMAND_COPY;
break;
case APPCOMMAND_CUT:
contentCommandMessage = NS_CONTENT_COMMAND_CUT;
break;
case APPCOMMAND_PASTE:
contentCommandMessage = NS_CONTENT_COMMAND_PASTE;
break;
case APPCOMMAND_REDO:
contentCommandMessage = NS_CONTENT_COMMAND_REDO;
break;
case APPCOMMAND_UNDO:
contentCommandMessage = NS_CONTENT_COMMAND_UNDO;
break;
}
if (contentCommandMessage) {
nsContentCommandEvent contentCommand(true, contentCommandMessage, this);
DispatchWindowEvent(&contentCommand);
// tell the driver that we handled the event
*aRetValue = 1;
result = true;
}
// default = false - tell the driver that the event was not handled
}

View File

@ -12,6 +12,7 @@
#include "nsAutoPtr.h"
#include "nsBaseWidget.h"
#include "nsWindowBase.h"
#include "nsdefs.h"
#include "nsIdleService.h"
#include "nsToolkit.h"
@ -64,7 +65,7 @@ class ModifierKeyState;
* Native WIN32 window wrapper.
*/
class nsWindow : public nsBaseWidget
class nsWindow : public nsWindowBase
{
typedef mozilla::TimeStamp TimeStamp;
typedef mozilla::TimeDuration TimeDuration;
@ -79,9 +80,11 @@ public:
friend class nsWindowGfx;
/**
* nsIWidget interface
*/
// nsWindowBase
virtual void InitEvent(nsGUIEvent& aEvent, nsIntPoint* aPoint = nullptr) MOZ_OVERRIDE;
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) MOZ_OVERRIDE;
// nsIWidget interface
NS_IMETHOD Create(nsIWidget *aParent,
nsNativeWidget aNativeParent,
const nsIntRect &aRect,
@ -186,13 +189,11 @@ public:
/**
* Event helpers
*/
void InitEvent(nsGUIEvent& event, nsIntPoint* aPoint = nullptr);
virtual bool DispatchMouseEvent(uint32_t aEventType, WPARAM wParam,
LPARAM lParam,
bool aIsContextMenuKey = false,
int16_t aButton = nsMouseEvent::eLeftButton,
uint16_t aInputSource = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE);
virtual bool DispatchWindowEvent(nsGUIEvent* event);
virtual bool DispatchWindowEvent(nsGUIEvent*event, nsEventStatus &aStatus);
void InitKeyEvent(nsKeyEvent& aKeyEvent,
const NativeKey& aNativeKey,
@ -215,7 +216,6 @@ public:
* Window utilities
*/
nsWindow* GetTopLevelWindow(bool aStopOnDialogOrPopup);
HWND GetWindowHandle() { return mWnd; }
WNDPROC GetPrevWindowProc() { return mPrevWndProc; }
WindowHook& GetWindowHook() { return mWindowHook; }
nsWindow* GetParentWindow(bool aIncludeOwner);

View File

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsWindowBase_h_
#define nsWindowBase_h_
#include "nsBaseWidget.h"
/*
* nsWindowBase - Base class of common methods other classes need to access
* in both win32 and winrt window classes.
*/
class nsWindowBase : public nsBaseWidget
{
public:
/*
* Return the HWND or null for this widget.
*/
virtual HWND GetWindowHandle() MOZ_FINAL {
return static_cast<HWND>(GetNativeData(NS_NATIVE_WINDOW));
}
/*
* Init a standard gecko event for this widget.
*/
virtual void InitEvent(nsGUIEvent& aEvent, nsIntPoint* aPoint = nullptr) = 0;
/*
* Dispatch a gecko event for this widget.
*/
virtual bool DispatchWindowEvent(nsGUIEvent* aEvent) = 0;
};
#endif // nsWindowBase_h_