Merge the last PGO-green inbound changeset to m-c.

This commit is contained in:
Ryan VanderMeulen 2012-07-14 19:14:51 -04:00
commit 9ec9fbfd2d
43 changed files with 753 additions and 163 deletions

View File

@ -194,8 +194,6 @@ static SETTING gDDESettings[] = {
{ MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
};
// See Bug 770883
#if 0
#if defined(MOZ_MAINTENANCE_SERVICE)
#define ONLY_SERVICE_LAUNCHING
@ -206,7 +204,6 @@ static const char *kPrefetchClearedPref =
"app.update.service.lastVersionPrefetchCleared";
static nsCOMPtr<nsIThread> sThread;
#endif
#endif
nsresult
GetHelperPath(nsAutoString& aPath)
@ -1004,8 +1001,6 @@ nsWindowsShellService::SetDesktopBackgroundColor(PRUint32 aColor)
nsWindowsShellService::nsWindowsShellService() :
mCheckedThisSession(false)
{
// See Bug 770883
#if 0
#if defined(MOZ_MAINTENANCE_SERVICE)
// Check to make sure the service is installed
@ -1050,13 +1045,10 @@ nsWindowsShellService::nsWindowsShellService() :
nsnull, CLEAR_PREFETCH_TIMEOUT_MS, nsITimer::TYPE_ONE_SHOT);
}
#endif
#endif
}
nsWindowsShellService::~nsWindowsShellService()
{
// See Bug 770883
#if 0
#if defined(MOZ_MAINTENANCE_SERVICE)
if (mTimer) {
mTimer->Cancel();
@ -1067,11 +1059,8 @@ nsWindowsShellService::~nsWindowsShellService()
sThread = nsnull;
}
#endif
#endif
}
// See Bug 770883
#if 0
#if defined(MOZ_MAINTENANCE_SERVICE)
class ClearPrefetchEvent : public nsRunnable {
@ -1094,7 +1083,6 @@ public:
}
};
#endif
#endif
/**
* For faster startup we attempt to clear the prefetch if the maintenance
@ -1105,8 +1093,6 @@ public:
* This is done on every update but also there is a one time operation done
* from within the program for first time installs.
*/
// See Bug 770883
#if 0
#if defined(MOZ_MAINTENANCE_SERVICE)
void
nsWindowsShellService::LaunchPrefetchClearCommand(nsITimer *aTimer, void*)
@ -1131,7 +1117,6 @@ nsWindowsShellService::LaunchPrefetchClearCommand(nsITimer *aTimer, void*)
}
}
#endif
#endif
NS_IMETHODIMP
nsWindowsShellService::OpenApplicationWithURI(nsIFile* aApplication,

View File

@ -1631,6 +1631,11 @@ public:
static nsresult ASCIIToUpper(nsAString& aStr);
static nsresult ASCIIToUpper(const nsAString& aSource, nsAString& aDest);
/**
* Return whether aStr contains an ASCII uppercase character.
*/
static bool StringContainsASCIIUpper(const nsAString& aStr);
// Returns NS_OK for same origin, error (NS_ERROR_DOM_BAD_URI) if not.
static nsresult CheckSameOrigin(nsIChannel *aOldChannel, nsIChannel *aNewChannel);
static nsIInterfaceRequestor* GetSameOriginChecker();

View File

@ -319,6 +319,39 @@ nsAttrAndChildArray::GetAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID) const
return nsnull;
}
const nsAttrValue*
nsAttrAndChildArray::GetAttr(const nsAString& aName,
nsCaseTreatment aCaseSensitive) const
{
// Check whether someone is being silly and passing non-lowercase
// attr names.
if (aCaseSensitive == eIgnoreCase &&
nsContentUtils::StringContainsASCIIUpper(aName)) {
// Try again with a lowercased name, but make sure we can't reenter this
// block by passing eCaseSensitive for aCaseSensitive.
nsAutoString lowercase;
nsContentUtils::ASCIIToLower(aName, lowercase);
return GetAttr(lowercase, eCaseMatters);
}
PRUint32 i, slotCount = AttrSlotCount();
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
if (ATTRS(mImpl)[i].mName.QualifiedNameEquals(aName)) {
return &ATTRS(mImpl)[i].mValue;
}
}
if (mImpl && mImpl->mMappedAttrs) {
const nsAttrValue* val =
mImpl->mMappedAttrs->GetAttr(aName);
if (val) {
return val;
}
}
return nsnull;
}
const nsAttrValue*
nsAttrAndChildArray::AttrAt(PRUint32 aPos) const
{
@ -490,8 +523,8 @@ PRInt32
nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID) const
{
PRInt32 idx;
if (mImpl && mImpl->mMappedAttrs) {
idx = mImpl->mMappedAttrs->IndexOfAttr(aLocalName, aNamespaceID);
if (mImpl && mImpl->mMappedAttrs && aNamespaceID == kNameSpaceID_None) {
idx = mImpl->mMappedAttrs->IndexOfAttr(aLocalName);
if (idx >= 0) {
return idx;
}

View File

@ -16,6 +16,7 @@
#include "nscore.h"
#include "nsAttrName.h"
#include "nsAttrValue.h"
#include "nsCaseTreatment.h"
class nsINode;
class nsIContent;
@ -71,6 +72,10 @@ public:
PRUint32 AttrCount() const;
const nsAttrValue* GetAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID = kNameSpaceID_None) const;
// Get an nsAttrValue by qualified name. Can optionally do
// ASCII-case-insensitive name matching.
const nsAttrValue* GetAttr(const nsAString& aName,
nsCaseTreatment aCaseSensitive) const;
const nsAttrValue* AttrAt(PRUint32 aPos) const;
nsresult SetAndTakeAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
nsresult SetAndTakeAttr(nsINodeInfo* aName, nsAttrValue& aValue);

View File

@ -5635,6 +5635,23 @@ nsContentUtils::EqualsLiteralIgnoreASCIICase(const nsAString& aStr1,
return true;
}
/* static */
bool
nsContentUtils::StringContainsASCIIUpper(const nsAString& aStr)
{
const PRUnichar* iter = aStr.BeginReading();
const PRUnichar* end = aStr.EndReading();
while (iter != end) {
PRUnichar c = *iter;
if (c >= 'A' && c <= 'Z') {
return true;
}
++iter;
}
return false;
}
/* static */
nsIInterfaceRequestor*
nsContentUtils::GetSameOriginChecker()

View File

@ -1536,22 +1536,30 @@ nsresult
nsGenericElement::GetAttribute(const nsAString& aName,
nsAString& aReturn)
{
const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
if (!name) {
if (mNodeInfo->NamespaceID() == kNameSpaceID_XUL) {
// I hate XUL
if (IsXUL()) {
const nsAttrValue* val =
nsXULElement::FromContent(this)->GetAttrValue(aName);
if (val) {
val->ToString(aReturn);
}
else {
// XXX should be SetDOMStringToNull(aReturn);
// See bug 232598
aReturn.Truncate();
}
else {
SetDOMStringToNull(aReturn);
}
return NS_OK;
}
GetAttr(name->NamespaceID(), name->LocalName(), aReturn);
const nsAttrValue* val =
mAttrsAndChildren.GetAttr(aName,
IsHTML() && IsInHTMLDocument() ?
eIgnoreCase : eCaseMatters);
if (val) {
val->ToString(aReturn);
} else {
SetDOMStringToNull(aReturn);
}
return NS_OK;
}

View File

@ -113,10 +113,23 @@ nsMappedAttributes::GetAttr(nsIAtom* aAttrName) const
{
NS_PRECONDITION(aAttrName, "null name");
PRInt32 i = IndexOfAttr(aAttrName, kNameSpaceID_None);
if (i >= 0) {
for (PRUint32 i = 0; i < mAttrCount; ++i) {
if (Attrs()[i].mName.Equals(aAttrName)) {
return &Attrs()[i].mValue;
}
}
return nsnull;
}
const nsAttrValue*
nsMappedAttributes::GetAttr(const nsAString& aAttrName) const
{
for (PRUint32 i = 0; i < mAttrCount; ++i) {
if (Attrs()[i].mName.Atom()->Equals(aAttrName)) {
return &Attrs()[i].mValue;
}
}
return nsnull;
}
@ -228,24 +241,14 @@ nsMappedAttributes::GetExistingAttrNameFromQName(const nsAString& aName) const
}
PRInt32
nsMappedAttributes::IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID) const
nsMappedAttributes::IndexOfAttr(nsIAtom* aLocalName) const
{
PRUint32 i;
if (aNamespaceID == kNameSpaceID_None) {
// This should be the common case so lets make an optimized loop
for (i = 0; i < mAttrCount; ++i) {
if (Attrs()[i].mName.Equals(aLocalName)) {
return i;
}
}
}
else {
for (i = 0; i < mAttrCount; ++i) {
if (Attrs()[i].mName.Equals(aLocalName, aNamespaceID)) {
return i;
}
}
}
return -1;
}

View File

@ -34,6 +34,7 @@ public:
nsresult SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue);
const nsAttrValue* GetAttr(nsIAtom* aAttrName) const;
const nsAttrValue* GetAttr(const nsAString& aAttrName) const;
PRUint32 Count() const
{
@ -67,7 +68,7 @@ public:
// aValue; any value that was already in aValue is destroyed.
void RemoveAttrAt(PRUint32 aPos, nsAttrValue& aValue);
const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
PRInt32 IndexOfAttr(nsIAtom* aLocalName, PRInt32 aNamespaceID) const;
PRInt32 IndexOfAttr(nsIAtom* aLocalName) const;
// nsIStyleRule

View File

@ -2449,7 +2449,7 @@ nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttribu
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
nsCSSValue* display = aData->ValueForDisplay();
if (display->GetUnit() == eCSSUnit_Null) {
if (aAttributes->IndexOfAttr(nsGkAtoms::hidden, kNameSpaceID_None) >= 0) {
if (aAttributes->IndexOfAttr(nsGkAtoms::hidden) >= 0) {
display->SetIntValue(NS_STYLE_DISPLAY_NONE, eCSSUnit_Enumerated);
}
}

View File

@ -1160,6 +1160,28 @@ nsXULElement::InternalGetExistingAttrNameFromQName(const nsAString& aStr) const
return nsnull;
}
const nsAttrValue*
nsXULElement::GetAttrValue(const nsAString& aName)
{
const nsAttrValue* val =
mAttrsAndChildren.GetAttr(aName, eCaseMatters);
if (val) {
return val;
}
if (mPrototype) {
PRUint32 i, count = mPrototype->mNumAttributes;
for (i = 0; i < count; ++i) {
nsXULPrototypeAttribute *protoAttr = &mPrototype->mAttributes[i];
if (protoAttr->mName.QualifiedNameEquals(aName)) {
return &protoAttr->mValue;
}
}
}
return nsnull;
}
bool
nsXULElement::GetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
nsAString& aResult) const

View File

@ -488,6 +488,8 @@ public:
mBindingParent = aBindingParent;
}
const nsAttrValue* GetAttrValue(const nsAString& aName);
/**
* Get the attr info for the given namespace ID and attribute name.
* The namespace ID must not be kNameSpaceID_Unknown and the name

View File

@ -9,9 +9,16 @@
#include "IDBFactory.h"
#include "nsIFile.h"
#include "nsIJSContextStack.h"
#include "nsIPrincipal.h"
#include "nsIScriptContext.h"
#include "nsIXPConnect.h"
#include "nsIXPCScriptable.h"
#include "jsdbgapi.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/storage.h"
#include "nsComponentManagerUtils.h"
#include "nsIScriptSecurityManager.h"
@ -34,14 +41,13 @@
#include "IndexedDatabaseManager.h"
#include "Key.h"
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/dom/TabChild.h"
using mozilla::dom::TabChild;
#include "ipc/IndexedDBChild.h"
USING_INDEXEDDB_NAMESPACE
using mozilla::dom::ContentChild;
using mozilla::dom::TabChild;
namespace {
struct ObjectStoreInfoMap
@ -56,7 +62,8 @@ struct ObjectStoreInfoMap
} // anonymous namespace
IDBFactory::IDBFactory()
: mOwningObject(nsnull), mActorChild(nsnull), mActorParent(nsnull)
: mOwningObject(nsnull), mActorChild(nsnull), mActorParent(nsnull),
mRootedOwningObject(false)
{
}
@ -68,6 +75,9 @@ IDBFactory::~IDBFactory()
mActorChild->Send__delete__(mActorChild);
NS_ASSERTION(!mActorChild, "Should have cleared in Send__delete__!");
}
if (mRootedOwningObject) {
NS_DROP_JS_OBJECTS(this, IDBFactory);
}
}
// static
@ -153,6 +163,92 @@ IDBFactory::Create(JSContext* aCx,
factory->mASCIIOrigin = origin;
factory->mOwningObject = aOwningObject;
if (!IndexedDatabaseManager::IsMainProcess()) {
ContentChild* contentChild = ContentChild::GetSingleton();
NS_ENSURE_TRUE(contentChild, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
IndexedDBChild* actor = new IndexedDBChild(origin);
contentChild->SendPIndexedDBConstructor(actor);
actor->SetFactory(factory);
}
factory.forget(aFactory);
return NS_OK;
}
// static
nsresult
IDBFactory::Create(IDBFactory** aFactory)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
#ifdef DEBUG
{
nsIThreadJSContextStack* cxStack = nsContentUtils::ThreadJSContextStack();
NS_ASSERTION(cxStack, "Couldn't get ThreadJSContextStack!");
JSContext* lastCx;
if (NS_SUCCEEDED(cxStack->Peek(&lastCx))) {
NS_ASSERTION(!lastCx, "We should only be called from C++!");
}
else {
NS_ERROR("nsIThreadJSContextStack::Peek should never fail!");
}
}
#endif
nsCString origin;
nsresult rv =
IndexedDatabaseManager::GetASCIIOriginFromWindow(nsnull, origin);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIPrincipal> principal =
do_CreateInstance("@mozilla.org/nullprincipal;1");
NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
JSContext* cx = nsContentUtils::GetSafeJSContext();
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
nsCxPusher pusher;
if (!pusher.Push(cx)) {
NS_WARNING("Failed to push safe JS context!");
return NS_ERROR_FAILURE;
}
JSAutoRequest ar(cx);
nsIXPConnect* xpc = nsContentUtils::XPConnect();
NS_ASSERTION(xpc, "This should never be null!");
nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
NS_ENSURE_SUCCESS(rv, rv);
JSObject* global;
rv = globalHolder->GetJSObject(&global);
NS_ENSURE_SUCCESS(rv, rv);
// The CreateSandbox call returns a proxy to the actual sandbox object. We
// don't need a proxy here.
global = JS_UnwrapObject(global);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, global)) {
NS_WARNING("Failed to enter compartment!");
return NS_ERROR_FAILURE;
}
nsRefPtr<IDBFactory> factory;
rv = Create(cx, global, getter_AddRefs(factory));
NS_ENSURE_SUCCESS(rv, rv);
NS_HOLD_JS_OBJECTS(factory, IDBFactory);
factory->mRootedOwningObject = true;
factory.forget(aFactory);
return NS_OK;
}
@ -389,6 +485,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IDBFactory)
if (tmp->mOwningObject) {
tmp->mOwningObject = nsnull;
}
if (tmp->mRootedOwningObject) {
NS_DROP_JS_OBJECTS(tmp, IDBFactory);
tmp->mRootedOwningObject = false;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

View File

@ -36,10 +36,12 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IDBFactory)
NS_DECL_NSIIDBFACTORY
// Called when using IndexedDB from a window in a different process.
static nsresult Create(nsPIDOMWindow* aWindow,
const nsACString& aASCIIOrigin,
IDBFactory** aFactory);
// Called when using IndexedDB from a window in the current process.
static nsresult Create(nsPIDOMWindow* aWindow,
nsIIDBFactory** aFactory)
{
@ -51,10 +53,16 @@ public:
return NS_OK;
}
// Called when using IndexedDB from a JS component or a JSM in the current
// process.
static nsresult Create(JSContext* aCx,
JSObject* aOwningObject,
IDBFactory** aFactory);
// Called when using IndexedDB from a JS component or a JSM in a different
// process.
static nsresult Create(IDBFactory** aFactory);
static already_AddRefed<mozIStorageConnection>
GetConnection(const nsAString& aDatabaseFilePath);
@ -90,6 +98,12 @@ public:
mActorParent = aActorParent;
}
const nsCString&
GetASCIIOrigin() const
{
return mASCIIOrigin;
}
private:
IDBFactory();
~IDBFactory();
@ -103,6 +117,8 @@ private:
IndexedDBChild* mActorChild;
IndexedDBParent* mActorParent;
bool mRootedOwningObject;
};
END_INDEXEDDB_NAMESPACE

View File

@ -22,6 +22,7 @@
namespace mozilla {
namespace dom {
class ContentParent;
class TabParent;
}
}
@ -129,6 +130,7 @@ public:
class IndexedDBParent : public PIndexedDBParent
{
friend class mozilla::dom::ContentParent;
friend class mozilla::dom::TabParent;
nsRefPtr<IDBFactory> mFactory;

View File

@ -31,10 +31,21 @@ LOCAL_INCLUDES += \
DEFINES += -D_IMPL_NS_LAYOUT
MOCHITEST_FILES = \
test_ipc.html \
$(NULL)
MOCHITEST_FILES = test_ipc.html
# Need to enable these tests sometime soon.
#XPCSHELL_TESTS = unit
# We're copying tests from another directory so this check is wrong for us.
#NO_XPCSHELL_MANIFEST_CHECK = 1
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk
include $(topsrcdir)/config/rules.mk
# Copy all the normal xpcshell tests from the regular unit directory.
copy-xpcshell-tests:
$(DIR_INSTALL) $(wildcard $(topsrcdir)/dom/indexedDB/test/unit/test_*.js) \
$(testxpcobjdir)/$(relativesrcdir)/$(XPCSHELL_TESTS)
libs-xpcshell-tests: copy-xpcshell-tests

View File

@ -3,6 +3,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
include protocol PBrowser;
include protocol PContent;
include protocol PIndexedDBDatabase;
include protocol PIndexedDBDeleteDatabaseRequest;
@ -12,7 +13,7 @@ namespace indexedDB {
protocol PIndexedDB
{
manager PBrowser;
manager PBrowser or PContent;
manages PIndexedDBDatabase;
manages PIndexedDBDeleteDatabaseRequest;

View File

@ -0,0 +1,18 @@
/**
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
const INDEXEDDB_UNIT_DIR = "../../test/unit/";
const INDEXEDDB_HEAD_FILE = INDEXEDDB_UNIT_DIR + "head.js";
function run_test() {
// IndexedDB needs a profile.
do_get_profile();
let thisTest = _TEST_FILE.toString().replace(/\\/g, "/");
thisTest = thisTest.substring(thisTest.lastIndexOf("/") + 1);
_HEAD_FILES.push(do_get_file(INDEXEDDB_HEAD_FILE).path.replace(/\\/g, "/"));
run_test_in_child(INDEXEDDB_UNIT_DIR + thisTest);
}

View File

@ -0,0 +1,60 @@
[DEFAULT]
head = head.js
tail =
# When adding files here please also update test/unit/xpcshell.ini!
[test_add_put.js]
[test_add_twice_failure.js]
[test_advance.js]
[test_autoIncrement_indexes.js]
[test_clear.js]
[test_complex_keyPaths.js]
[test_count.js]
[test_create_index.js]
[test_create_index_with_integer_keys.js]
[test_create_objectStore.js]
[test_cursor_mutation.js]
[test_cursor_update_updates_indexes.js]
[test_cursors.js]
[test_deleteDatabase.js]
[test_event_source.js]
[test_getAll.js]
[test_global_data.js]
[test_index_empty_keyPath.js]
[test_index_getAll.js]
[test_index_getAllObjects.js]
[test_index_object_cursors.js]
[test_index_update_delete.js]
[test_indexes.js]
[test_indexes_bad_values.js]
[test_key_requirements.js]
[test_keys.js]
[test_multientry.js]
[test_names_sorted.js]
[test_object_identity.js]
[test_objectCursors.js]
[test_objectStore_inline_autoincrement_key_added_on_put.js]
[test_objectStore_remove_values.js]
[test_odd_result_order.js]
[test_open_empty_db.js]
[test_open_objectStore.js]
[test_optionalArguments.js]
[test_overlapping_transactions.js]
[test_put_get_values.js]
[test_put_get_values_autoIncrement.js]
[test_remove_index.js]
[test_remove_objectStore.js]
[test_request_readyState.js]
[test_setVersion.js]
[test_setVersion_abort.js]
[test_setVersion_events.js]
[test_setVersion_exclusion.js]
[test_success_events_after_abort.js]
[test_traffic_jam.js]
[test_transaction_abort.js]
[test_transaction_lifetimes.js]
[test_transaction_lifetimes_nested.js]
[test_transaction_ordering.js]
# When adding files here please also update test/unit/xpcshell.ini!

View File

@ -7,10 +7,11 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = dom/indexedDB/test
DIRS += unit
include $(DEPTH)/config/autoconf.mk
TEST_DIRS = unit
XPCSHELL_TESTS = unit
MOCHITEST_FILES = \
@ -125,4 +126,3 @@ MOCHITEST_BROWSER_FILES = \
endif
include $(topsrcdir)/config/rules.mk

View File

@ -16,13 +16,6 @@ const IDBIndex = Ci.nsIIDBIndex
const IDBObjectStore = Ci.nsIIDBObjectStore
const IDBRequest = Ci.nsIIDBRequest
// XPCShell does not get a profile by default.
do_get_profile();
var idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"].
getService(Ci.nsIIndexedDatabaseManager);
idbManager.initWindowless(this);
function is(a, b, msg) {
dump("is(" + a + ", " + b + ", \"" + msg + "\")");
do_check_eq(a, b, Components.stack.caller);
@ -52,6 +45,13 @@ function run_test() {
function runTest()
{
// XPCShell does not get a profile by default.
do_get_profile();
var idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"].
getService(Ci.nsIIndexedDatabaseManager);
idbManager.initWindowless(this);
do_test_pending();
testGenerator.next();
}

View File

@ -1,7 +1,9 @@
[DEFAULT]
head = head_idb.js
head = head.js
tail =
# When adding files here please also update ipc/unit/xpcshell.ini!
[test_add_put.js]
[test_add_twice_failure.js]
[test_advance.js]
@ -54,3 +56,5 @@ tail =
[test_transaction_lifetimes.js]
[test_transaction_lifetimes_nested.js]
[test_transaction_ordering.js]
# When adding files here please also update ipc/unit/xpcshell.ini!

View File

@ -88,6 +88,7 @@ using namespace mozilla::places;
using namespace mozilla::docshell;
using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::sms;
using namespace mozilla::dom::indexedDB;
namespace mozilla {
namespace dom {
@ -429,6 +430,20 @@ ContentChild::DeallocPHal(PHalChild* aHal)
return true;
}
PIndexedDBChild*
ContentChild::AllocPIndexedDB()
{
NS_NOTREACHED("Should never get here!");
return NULL;
}
bool
ContentChild::DeallocPIndexedDB(PIndexedDBChild* aActor)
{
delete aActor;
return true;
}
PTestShellChild*
ContentChild::AllocPTestShell()
{

View File

@ -71,6 +71,9 @@ public:
NS_OVERRIDE virtual PHalChild* AllocPHal();
NS_OVERRIDE virtual bool DeallocPHal(PHalChild*);
virtual PIndexedDBChild* AllocPIndexedDB();
virtual bool DeallocPIndexedDB(PIndexedDBChild* aActor);
virtual PMemoryReportRequestChild*
AllocPMemoryReportRequest();

View File

@ -83,6 +83,10 @@
#include "nsDirectoryServiceDefs.h"
#include "mozilla/Preferences.h"
#include "IDBFactory.h"
#include "IndexedDatabaseManager.h"
#include "IndexedDBParent.h"
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
@ -95,6 +99,7 @@ using mozilla::unused; // heh
using base::KillProcess;
using namespace mozilla::dom::devicestorage;
using namespace mozilla::dom::sms;
using namespace mozilla::dom::indexedDB;
namespace mozilla {
namespace dom {
@ -829,6 +834,42 @@ ContentParent::DeallocPHal(PHalParent* aHal)
return true;
}
PIndexedDBParent*
ContentParent::AllocPIndexedDB()
{
return new IndexedDBParent();
}
bool
ContentParent::DeallocPIndexedDB(PIndexedDBParent* aActor)
{
delete aActor;
return true;
}
bool
ContentParent::RecvPIndexedDBConstructor(PIndexedDBParent* aActor)
{
nsRefPtr<IndexedDatabaseManager> mgr = IndexedDatabaseManager::GetOrCreate();
NS_ENSURE_TRUE(mgr, false);
if (!IndexedDatabaseManager::IsMainProcess()) {
NS_RUNTIMEABORT("Not supported yet!");
}
nsRefPtr<IDBFactory> factory;
nsresult rv = IDBFactory::Create(getter_AddRefs(factory));
NS_ENSURE_SUCCESS(rv, false);
NS_ASSERTION(factory, "This should never be null!");
IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor);
actor->mFactory = factory;
actor->mASCIIOrigin = factory->GetASCIIOrigin();
return true;
}
PMemoryReportRequestParent*
ContentParent::AllocPMemoryReportRequest()
{

View File

@ -123,6 +123,13 @@ private:
NS_OVERRIDE virtual PHalParent* AllocPHal();
NS_OVERRIDE virtual bool DeallocPHal(PHalParent*);
virtual PIndexedDBParent* AllocPIndexedDB();
virtual bool DeallocPIndexedDB(PIndexedDBParent* aActor);
virtual bool
RecvPIndexedDBConstructor(PIndexedDBParent* aActor);
virtual PMemoryReportRequestParent* AllocPMemoryReportRequest();
virtual bool DeallocPMemoryReportRequest(PMemoryReportRequestParent* actor);

View File

@ -10,6 +10,7 @@ include protocol PCrashReporter;
include protocol PExternalHelperApp;
include protocol PDeviceStorageRequest;
include protocol PHal;
include protocol PIndexedDB;
include protocol PMemoryReportRequest;
include protocol PNecko;
include protocol PSms;
@ -102,6 +103,7 @@ rpc protocol PContent
manages PDeviceStorageRequest;
manages PExternalHelperApp;
manages PHal;
manages PIndexedDB;
manages PMemoryReportRequest;
manages PNecko;
manages PSms;
@ -167,6 +169,8 @@ parent:
PHal();
PIndexedDB();
PNecko();
PSms();

View File

@ -244,7 +244,7 @@ protected:
virtual PIndexedDBChild* AllocPIndexedDB(const nsCString& aASCIIOrigin,
bool* /* aAllowed */);
virtual bool DeallocPIndexedDB(PIndexedDBChild* actor);
virtual bool DeallocPIndexedDB(PIndexedDBChild* aActor);
private:
void ActorDestroy(ActorDestroyReason why);

View File

@ -400,6 +400,7 @@ class State(Node):
State.ANY = State(Loc.NONE, '[any]', start=True)
State.DEAD = State(Loc.NONE, '[dead]', start=False)
State.DYING = State(Loc.NONE, '[dying]', start=False)
class Param(Node):
def __init__(self, loc, typespec, name):

View File

@ -147,6 +147,11 @@ def _deadState(proto=None):
if proto is not None: pfx = proto.name() +'::'
return ExprVar(pfx +'__Dead')
def _dyingState(proto=None):
pfx = ''
if proto is not None: pfx = proto.name() +'::'
return ExprVar(pfx +'__Dying')
def _startState(proto=None, fq=False):
pfx = ''
if proto:
@ -157,6 +162,9 @@ def _startState(proto=None, fq=False):
def _deleteId():
return ExprVar('Msg___delete____ID')
def _deleteReplyId():
return ExprVar('Reply___delete____ID')
def _lookupListener(idexpr):
return ExprCall(ExprVar('Lookup'), args=[ idexpr ])
@ -1494,6 +1502,7 @@ class _GenerateProtocolCode(ipdl.ast.Visitor):
stateenum.addId(_deadState().name)
stateenum.addId(_nullState().name)
stateenum.addId(_errorState().name)
stateenum.addId(_dyingState().name)
for ts in p.transitionStmts:
stateenum.addId(ts.state.decl.cxxname)
if len(p.transitionStmts):
@ -1658,8 +1667,12 @@ class _GenerateProtocolCode(ipdl.ast.Visitor):
nullerrorblock = Block()
if ptype.hasDelete:
ifdelete = StmtIf(ExprBinary(_deleteId(), '==', msgexpr))
if ptype.hasReentrantDelete:
nextState = _dyingState()
else:
nextState = _deadState()
ifdelete.addifstmts([
StmtExpr(ExprAssn(ExprDeref(nextvar), _deadState())),
StmtExpr(ExprAssn(ExprDeref(nextvar), nextState)),
StmtReturn(ExprLiteral.TRUE) ])
nullerrorblock.addstmt(ifdelete)
nullerrorblock.addstmt(
@ -1674,6 +1687,21 @@ class _GenerateProtocolCode(ipdl.ast.Visitor):
StmtReturn(ExprLiteral.FALSE) ])
fromswitch.addcase(CaseLabel(_deadState().name), deadblock)
# special case for Dying
dyingblock = Block()
if ptype.hasReentrantDelete:
ifdelete = StmtIf(ExprBinary(_deleteReplyId(), '==', msgexpr))
ifdelete.addifstmt(
StmtExpr(ExprAssn(ExprDeref(nextvar), _deadState())))
dyingblock.addstmt(ifdelete)
dyingblock.addstmt(
StmtReturn(ExprLiteral.TRUE))
else:
dyingblock.addstmts([
_runtimeAbort('__delete__()d (and unexpectedly dying) actor'),
StmtReturn(ExprLiteral.FALSE) ])
fromswitch.addcase(CaseLabel(_dyingState().name), dyingblock)
unreachedblock = Block()
unreachedblock.addstmts([
_runtimeAbort('corrupted actor state'),
@ -2912,6 +2940,21 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
method.addstmts([ routedecl, routeif, Whitespace.NL ])
# in the event of an RPC delete message, we want to loudly complain about
# messages that are received that are not a reply to the original message
if ptype.hasReentrantDelete:
msgVar = ExprVar(params[0].name)
ifdying = StmtIf(ExprBinary(
ExprBinary(ExprVar('mState'), '==', _dyingState(ptype)),
'&&',
ExprBinary(
ExprBinary(ExprCall(ExprSelect(msgVar, '.', 'is_reply')), '!=', ExprLiteral.TRUE),
'||',
ExprBinary(ExprCall(ExprSelect(msgVar, '.', 'is_rpc')), '!=', ExprLiteral.TRUE))))
ifdying.addifstmts([_fatalError('incoming message racing with actor deletion'),
StmtReturn(_Result.Processed)])
method.addstmt(ifdying)
# bug 509581: don't generate the switch stmt if there
# is only the default case; MSVC doesn't like that
if switch.nr_cases > 1:
@ -4527,9 +4570,13 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
ifsendok.addifstmts([ Whitespace.NL,
StmtExpr(ExprAssn(sendok, ExprLiteral.FALSE, '&=')) ])
method.addstmt(ifsendok)
if self.protocol.decl.type.hasReentrantDelete:
method.addstmts(self.transition(md, 'in', actor.var(), reply=True))
method.addstmts(
[ ifsendok ]
+ self.dtorEpilogue(md, actor.var())
self.dtorEpilogue(md, actor.var())
+ [ Whitespace.NL, StmtReturn(sendok) ])
return method
@ -4907,7 +4954,7 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
saveIdStmts = [ ]
return idvar, saveIdStmts
def transition(self, md, direction, actor=None):
def transition(self, md, direction, actor=None, reply=False):
if actor is not None: stateexpr = _actorState(actor)
else: stateexpr = self.protocol.stateVar()
@ -4919,12 +4966,13 @@ class _GenerateProtocolActorCode(ipdl.ast.Visitor):
action = ExprVar('Trigger::Recv')
else: assert 0 and 'unknown combo %s/%s'% (self.side, direction)
msgid = md.pqMsgId() if not reply else md.pqReplyId()
ifbad = StmtIf(ExprNot(
ExprCall(
ExprVar(self.protocol.name +'::Transition'),
args=[ stateexpr,
ExprCall(ExprVar('Trigger'),
args=[ action, ExprVar(md.pqMsgId()) ]),
args=[ action, ExprVar(msgid) ]),
ExprAddrOf(stateexpr) ])))
ifbad.addifstmts(_badTransition())
return [ ifbad ]

View File

@ -271,6 +271,7 @@ class ProtocolType(IPDLType):
self.manages = [ ]
self.stateless = stateless
self.hasDelete = False
self.hasReentrantDelete = False
def isProtocol(self): return True
def name(self):
@ -827,6 +828,8 @@ class GatherDecls(TcheckVisitor):
"destructor declaration `%s(...)' required for managed protocol `%s'",
_DELETE_MSG, p.name)
p.decl.type.hasReentrantDelete = p.decl.type.hasDelete and self.symtab.lookup(_DELETE_MSG).type.isRpc()
for managed in p.managesStmts:
mgdname = managed.name
ctordecl = self.symtab.lookup(mgdname +'Constructor')
@ -845,13 +848,17 @@ class GatherDecls(TcheckVisitor):
if 0 == len(p.startStates):
p.startStates = [ p.transitionStmts[0] ]
# declare implicit "any" and "dead" states
# declare implicit "any", "dead", and "dying" states
self.declare(loc=State.ANY.loc,
type=StateType(p.decl.type, State.ANY.name, start=False),
progname=State.ANY.name)
self.declare(loc=State.DEAD.loc,
type=StateType(p.decl.type, State.DEAD.name, start=False),
progname=State.DEAD.name)
if p.decl.type.hasReentrantDelete:
self.declare(loc=State.DYING.loc,
type=StateType(p.decl.type, State.DYING.name, start=False),
progname=State.DYING.name)
# declare each state before decorating their mention
for trans in p.transitionStmts:
@ -871,6 +878,9 @@ class GatherDecls(TcheckVisitor):
# add a special state |state DEAD: null goto DEAD;|
deadtrans = TransitionStmt.makeNullStmt(State.DEAD)
p.states[State.DEAD] = deadtrans
if p.decl.type.hasReentrantDelete:
dyingtrans = TransitionStmt.makeNullStmt(State.DYING)
p.states[State.DYING] = dyingtrans
# visit the message decls once more and resolve the state names
# attached to actor params and returns

View File

@ -3,13 +3,13 @@
* 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 "nsRegion.h"
#include "mozilla/ipc/IOThreadChild.h"
#include "IPDLUnitTestProcessChild.h"
#include "IPDLUnitTests.h"
#include "nsRegion.h"
using mozilla::ipc::IOThreadChild;
namespace mozilla {

View File

@ -111,7 +111,7 @@ ${ENUM_TO_STRINGS}
IPDLUnitTestType
IPDLUnitTest()
{
return IPDLUnitTestFromString(mozilla::_ipdltest::IPDLUnitTestName());
return IPDLUnitTestFromString(::mozilla::_ipdltest::IPDLUnitTestName());
}
@ -250,7 +250,7 @@ DeleteParentActor()
//===== TEMPLATED =====
${PARENT_DELETE_CASES}
//-----------------------------------------------------------------------------
default: mozilla::_ipdltest::fail("???");
default: ::mozilla::_ipdltest::fail("???");
}
}
@ -353,7 +353,7 @@ DeleteChildActor()
//===== TEMPLATED =====
${CHILD_DELETE_CASES}
//-----------------------------------------------------------------------------
default: mozilla::_ipdltest::fail("???");
default: ::mozilla::_ipdltest::fail("???");
}
}

View File

@ -54,6 +54,7 @@ IPDLTESTS = \
TestSyncError \
TestSyncHang \
TestSyncWakeup \
TestBadActor \
$(NULL)
ifeq ($(OS_ARCH),Linux)

View File

@ -0,0 +1,18 @@
include protocol PTestBadActorSub;
namespace mozilla {
namespace _ipdltest {
// Test that a parent sending a reentrant __delete__ message
// is not killed if a child's message races with the reply.
rpc protocol PTestBadActor {
manages PTestBadActorSub;
child:
PTestBadActorSub();
__delete__();
};
} // namespace _ipdltest
} // namespace mozilla

View File

@ -0,0 +1,17 @@
include protocol PTestBadActor;
namespace mozilla {
namespace _ipdltest {
rpc protocol PTestBadActorSub {
manager PTestBadActor;
child:
rpc __delete__();
parent:
Ping();
};
} // namespace _ipdltest
} // namespace mozilla

View File

@ -0,0 +1,51 @@
#include "TestBadActor.h"
#include "IPDLUnitTests.h"
#include "mozilla/unused.h"
namespace mozilla {
namespace _ipdltest {
void
TestBadActorParent::Main()
{
// This test is designed to test a race condition where the child sends us
// a message on an actor that we've already destroyed. The child process
// should die, and the parent process should not abort.
PTestBadActorSubParent* child = SendPTestBadActorSubConstructor();
if (!child)
fail("Sending constructor");
unused << child->Call__delete__(child);
}
PTestBadActorSubParent*
TestBadActorParent::AllocPTestBadActorSub()
{
return new TestBadActorSubParent();
}
bool
TestBadActorSubParent::RecvPing()
{
fail("Shouldn't have received ping.");
return false;
}
PTestBadActorSubChild*
TestBadActorChild::AllocPTestBadActorSub()
{
return new TestBadActorSubChild();
}
bool
TestBadActorChild::RecvPTestBadActorSubConstructor(PTestBadActorSubChild* actor)
{
if (!actor->SendPing()) {
fail("Couldn't send ping to an actor which supposedly isn't dead yet.");
}
return true;
}
} // namespace _ipdltest
} // namespace mozilla

View File

@ -0,0 +1,91 @@
#ifndef mozilla__ipdltest_TestBadActor_h
#define mozilla__ipdltest_TestBadActor_h
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/PTestBadActorParent.h"
#include "mozilla/_ipdltest/PTestBadActorChild.h"
#include "mozilla/_ipdltest/PTestBadActorSubParent.h"
#include "mozilla/_ipdltest/PTestBadActorSubChild.h"
namespace mozilla {
namespace _ipdltest {
class TestBadActorParent
: public PTestBadActorParent
{
public:
TestBadActorParent() { }
virtual ~TestBadActorParent() { }
static bool RunTestInProcesses() { return true; }
static bool RunTestInThreads() { return false; }
void Main();
protected:
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why)
{
if (AbnormalShutdown != why)
fail("unexpected destruction");
passed("ok");
QuitParent();
}
virtual PTestBadActorSubParent*
AllocPTestBadActorSub();
virtual bool
DeallocPTestBadActorSub(PTestBadActorSubParent* actor) {
delete actor;
return true;
}
};
class TestBadActorSubParent
: public PTestBadActorSubParent
{
public:
TestBadActorSubParent() { }
virtual ~TestBadActorSubParent() { }
protected:
virtual bool RecvPing();
};
class TestBadActorChild
: public PTestBadActorChild
{
public:
TestBadActorChild() { }
virtual ~TestBadActorChild() { }
protected:
virtual PTestBadActorSubChild*
AllocPTestBadActorSub();
virtual bool
DeallocPTestBadActorSub(PTestBadActorSubChild* actor)
{
delete actor;
return true;
}
virtual bool
RecvPTestBadActorSubConstructor(PTestBadActorSubChild* actor);
};
class TestBadActorSubChild
: public PTestBadActorSubChild
{
public:
TestBadActorSubChild() { }
virtual ~TestBadActorSubChild() { }
};
} // namespace _ipdltest
} // namespace mozilla
#endif // mozilla__ipdltest_TestBadActor_h

View File

@ -24,6 +24,12 @@ public:
{ }
virtual ~TestDataStructuresSub()
{ }
NS_OVERRIDE
virtual void ActorDestroy(ActorDestroyReason why)
{
if (Deletion != why)
fail("unexpected destruction!");
}
uint32 mI;
};

View File

@ -94,9 +94,9 @@ def main(argv):
reinterpret_cast<%sChild**>(&gChildActor);
*child = new %sChild();
mozilla::ipc::AsyncChannel *childChannel = (*child)->GetIPCChannel();
mozilla::ipc::AsyncChannel::Side parentSide =
mozilla::ipc::AsyncChannel::Parent;
::mozilla::ipc::AsyncChannel *childChannel = (*child)->GetIPCChannel();
::mozilla::ipc::AsyncChannel::Side parentSide =
::mozilla::ipc::AsyncChannel::Parent;
(*parent)->Open(childChannel, childMessageLoop, parentSide);
return (*parent)->Main();

View File

@ -45,4 +45,6 @@ IPDLSRCS = \
PTestSyncHang.ipdl \
PTestSyncWakeup.ipdl \
PTestSysVShmem.ipdl \
PTestBadActor.ipdl \
PTestBadActorSub.ipdl \
$(NULL)

View File

@ -1497,7 +1497,7 @@ var SelectionHandler = {
if (zoom != this._viewOffset.zoom) {
this._viewOffset.zoom = zoom;
this.updateCacheForSelection();
this.positionHandles();
this.positionHandles(true);
}
break;
}
@ -1604,7 +1604,7 @@ var SelectionHandler = {
QueryInterface(Ci.nsISelectionController);
selectionController.selectAll();
this.updateCacheForSelection();
this.positionHandles();
this.positionHandles(false);
break;
}
case COPY: {
@ -1645,13 +1645,12 @@ var SelectionHandler = {
*/
// Update the handle position as it's dragged
if (aIsStartHandle) {
this._start.style.left = aX + this._view.scrollX - this._viewOffset.left + "px";
this._start.style.top = aY + this._view.scrollY - this._viewOffset.top + "px";
} else {
this._end.style.left = aX + this._view.scrollX - this._viewOffset.left + "px";
this._end.style.top = aY + this._view.scrollY - this._viewOffset.top + "px";
}
let leftTop = "left:" + (aX + this._view.scrollX - this._viewOffset.left) + "px;" +
"top:" + (aY + this._view.scrollY - this._viewOffset.top) + "px;";
if (aIsStartHandle)
this._start.style.cssText = this._start.style.cssText + leftTop;
else
this._end.style.cssText = this._end.style.cssText + leftTop;
let cwu = this._view.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
@ -1742,21 +1741,24 @@ var SelectionHandler = {
if (this._view) {
let selection = this._view.getSelection();
if (selection) {
// Get the text to copy if the tap is in the selection
if (arguments.length == 2 && this._pointInSelection(aX, aY))
selectedText = selection.toString().trim();
selection.removeAllRanges();
selection.QueryInterface(Ci.nsISelectionPrivate).removeSelectionListener(this);
}
}
// Only try copying text if there's text to copy!
if (arguments.length == 2 && selectedText.length) {
if (selectedText.length) {
let contentWindow = BrowserApp.selectedBrowser.contentWindow;
let element = ElementTouchHelper.elementFromPoint(contentWindow, aX, aY);
if (!element)
element = ElementTouchHelper.anyElementFromPoint(contentWindow, aX, aY);
// Only try copying text if the tap happens in the same view
if (element.ownerDocument.defaultView == this._view && this._pointInSelection(aX, aY)) {
if (element.ownerDocument.defaultView == this._view) {
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
clipboard.copyString(selectedText, element.ownerDocument);
NativeWindow.toast.show(Strings.browser.GetStringFromName("selectionHelper.textCopied"), "short");
@ -1784,20 +1786,18 @@ var SelectionHandler = {
win = win.parent;
}
let rangeRect = this._view.getSelection().getRangeAt(0).getBoundingClientRect();
let radius = ElementTouchHelper.getTouchRadius();
return (aX - offset.x > this.cache.rect.left - radius.left &&
aX - offset.x < this.cache.rect.right + radius.right &&
aY - offset.y > this.cache.rect.top - radius.top &&
aY - offset.y < this.cache.rect.bottom + radius.bottom);
return (aX - offset.x > rangeRect.left - radius.left &&
aX - offset.x < rangeRect.right + radius.right &&
aY - offset.y > rangeRect.top - radius.top &&
aY - offset.y < rangeRect.bottom + radius.bottom);
},
// Returns true if the selection has been reversed. Takes optional aIsStartHandle
// param to decide whether the selection has been reversed.
updateCacheForSelection: function sh_updateCacheForSelection(aIsStartHandle) {
let range = this._view.getSelection().getRangeAt(0);
this.cache.rect = range.getBoundingClientRect();
let rects = range.getClientRects();
let rects = this._view.getSelection().getRangeAt(0).getClientRects();
let start = { x: rects[0].left, y: rects[0].bottom };
let end = { x: rects[rects.length - 1].right, y: rects[rects.length - 1].bottom };
@ -1816,22 +1816,28 @@ var SelectionHandler = {
// Adjust start/end positions to account for scroll, and account for the dimensions of the
// handle elements to ensure the handles point exactly at the ends of the selection.
positionHandles: function sh_positionHandles() {
let height = this.HANDLE_HEIGHT / this._viewOffset.zoom;
this._start.style.height = height + "px";
this._end.style.height = height + "px";
positionHandles: function sh_positionHandles(adjustScale) {
let startCss = this._start.style.cssText;
let endCss = this._end.style.cssText;
let width = this.HANDLE_WIDTH/ this._viewOffset.zoom;
this._start.style.width = width + "px";
this._end.style.width = width + "px";
if (adjustScale) {
let heightWidth = "height:" + this.HANDLE_HEIGHT / this._viewOffset.zoom + "px;" +
"width:" + this.HANDLE_WIDTH / this._viewOffset.zoom + "px;";
this._start.style.left = (this.cache.start.x + this._view.scrollX - this._viewOffset.left -
this.HANDLE_PADDING - this.HANDLE_HORIZONTAL_OFFSET - width) + "px";
this._start.style.top = (this.cache.start.y + this._view.scrollY - this._viewOffset.top) + "px";
startCss += heightWidth;
endCss += heightWidth;
}
this._end.style.left = (this.cache.end.x + this._view.scrollX - this._viewOffset.left -
this.HANDLE_PADDING + this.HANDLE_HORIZONTAL_OFFSET) + "px";
this._end.style.top = (this.cache.end.y + this._view.scrollY - this._viewOffset.top) + "px";
startCss += "left:" + (this.cache.start.x + this._view.scrollX - this._viewOffset.left -
this.HANDLE_PADDING - this.HANDLE_HORIZONTAL_OFFSET - this.HANDLE_WIDTH / this._viewOffset.zoom) + "px;" +
"top:" + (this.cache.start.y + this._view.scrollY - this._viewOffset.top) + "px;";
endCss += "left:" + (this.cache.end.x + this._view.scrollX - this._viewOffset.left -
this.HANDLE_PADDING + this.HANDLE_HORIZONTAL_OFFSET) + "px;" +
"top:" + (this.cache.end.y + this._view.scrollY - this._viewOffset.top) + "px;";
this._start.style.cssText = startCss;
this._end.style.cssText = endCss;
},
showHandles: function sh_showHandles() {
@ -1845,7 +1851,7 @@ var SelectionHandler = {
return;
}
this.positionHandles();
this.positionHandles(true);
this._start.setAttribute("showing", "true");
this._end.setAttribute("showing", "true");
@ -1906,7 +1912,7 @@ var SelectionHandler = {
this._touchDelta = null;
// Adjust the handles to be in the correct spot relative to the text selection
this.positionHandles();
this.positionHandles(false);
break;
case "touchmove":

View File

@ -37,23 +37,10 @@ WritePrefetchClearedReg()
return TRUE;
}
static BOOL
PrefetchFileAlreadyCleared(LPCWSTR prefetchPath)
{
DWORD attributes = GetFileAttributes(prefetchPath);
BOOL alreadyCleared = attributes != INVALID_FILE_ATTRIBUTES &&
attributes & FILE_ATTRIBUTE_READONLY;
nsAutoHandle prefetchFile(CreateFile(prefetchPath, GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL));
LARGE_INTEGER fileSize = { 0, 0 };
alreadyCleared &= prefetchFile != INVALID_HANDLE_VALUE &&
GetFileSizeEx(prefetchFile, &fileSize) &&
fileSize.QuadPart == 0;
return alreadyCleared;
}
/**
* Update: We found that prefetch clearing was a net negative, so this
* function has been updated to delete the read only prefetch files.
* -----------------------------------------------------------------------
* We found that prefetch actually causes large applications like Firefox
* to startup slower. This will get rid of the Windows prefetch files for
* applications like firefox (FIREFOX-*.pf files) and instead replace them
@ -159,40 +146,34 @@ ClearPrefetch(LPCWSTR prefetchProcessName)
continue;
}
if (PrefetchFileAlreadyCleared(prefetchPath)) {
++deletedCount;
LOG(("Prefetch file already cleared: %ls\n", prefetchPath));
continue;
}
// Delete the prefetch file and replace it with a blank read only file
HANDLE prefetchFile =
CreateFile(prefetchPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (INVALID_HANDLE_VALUE == prefetchFile) {
LOG(("Error replacing prefetch path %ls. (%d)\n", findFileData.cFileName,
GetLastError()));
deletedAllFFPrefetch = FALSE;
continue;
}
CloseHandle(prefetchFile);
DWORD attributes = GetFileAttributes(prefetchPath);
DWORD attributes = GetFileAttributesW(prefetchPath);
if (INVALID_FILE_ATTRIBUTES == attributes) {
LOG(("Could not get/set attributes on prefetch file: %ls. (%d)\n",
findFileData.cFileName, GetLastError()));
continue;
}
if (!SetFileAttributes(prefetchPath,
attributes | FILE_ATTRIBUTE_READONLY)) {
if (!(attributes & FILE_ATTRIBUTE_READONLY)) {
LOG(("Prefetch file is not read-only, don't clear: %ls.\n",
findFileData.cFileName));
continue;
}
// Remove the read only attribute so a DeleteFile call will work.
if (!SetFileAttributesW(prefetchPath,
attributes & (~FILE_ATTRIBUTE_READONLY))) {
LOG(("Could not set read only on prefetch file: %ls. (%d)\n",
findFileData.cFileName, GetLastError()));
continue;
}
if (!DeleteFileW(prefetchPath)) {
LOG(("Could not delete read only prefetch file: %ls. (%d)\n",
findFileData.cFileName, GetLastError()));
}
++deletedCount;
LOG(("Prefetch file cleared and set to read-only successfully: %ls\n",
LOG(("Prefetch file cleared successfully: %ls\n",
prefetchPath));
} while (FindNextFileW(findHandle, &findFileData));
LOG(("Done searching prefetch paths. (%d)\n", GetLastError()));

View File

@ -504,14 +504,9 @@ ExecuteServiceCommand(int argc, LPWSTR *argv)
// because the service self updates itself and the service
// installer will stop the service.
LOG(("Service command %ls complete.\n", argv[2]));
}
// See Bug 770883
#if 0
else if (!lstrcmpi(argv[2], L"clear-prefetch")) {
} else if (!lstrcmpi(argv[2], L"clear-prefetch")) {
result = ClearKnownPrefetch();
}
#endif
else {
} else {
LOG(("Service command not recognized: %ls.\n", argv[2]));
// result is already set to FALSE
}