Merge mozilla-central to autoland

This commit is contained in:
Carsten "Tomcat" Book 2017-08-09 12:31:56 +02:00
Родитель d9fddc6423 c329d562fb
Коммит bb29fe249d
122 изменённых файлов: 2641 добавлений и 2059 удалений

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsTextEquivUtils.h"
#include "DocAccessibleChild.h"
#include "EventTree.h"
#include "GeckoProfiler.h"
#include "Relation.h"
#include "Role.h"
#include "RootAccessible.h"
@ -844,6 +845,13 @@ Accessible::HandleAccEvent(AccEvent* aEvent)
{
NS_ENSURE_ARG_POINTER(aEvent);
if (profiler_is_active()) {
nsAutoCString strEventType;
GetAccService()->GetStringEventType(aEvent->GetEventType(), strEventType);
profiler_tracing("A11y Event", strEventType.get());
}
if (IPCAccessibilityActive() && Document()) {
DocAccessibleChild* ipcDoc = mDoc->IPCDoc();
MOZ_ASSERT(ipcDoc);

Просмотреть файл

@ -50,6 +50,10 @@ this.ControlCenter = {
await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
await openIdentityPopup();
},
async verifyConfig() {
return Promise.reject("Bug 1373563: intermittent controlCenter_localFile on Taskcluster");
},
},
http: {
@ -82,7 +86,7 @@ this.ControlCenter = {
singlePermission: {
async applyConfig() {
let uri = Services.io.newURI(PERMISSIONS_PAGE)
let uri = Services.io.newURI(PERMISSIONS_PAGE);
SitePermissions.set(uri, "camera", SitePermissions.ALLOW);
await loadPage(PERMISSIONS_PAGE);
@ -95,7 +99,7 @@ this.ControlCenter = {
// TODO: (Bug 1330601) Rewrite this to consider temporary (TAB) permission states.
// There are 2 possible non-default permission states, so we alternate between them.
let states = [SitePermissions.ALLOW, SitePermissions.BLOCK];
let uri = Services.io.newURI(PERMISSIONS_PAGE)
let uri = Services.io.newURI(PERMISSIONS_PAGE);
SitePermissions.listPermissions().forEach(function(permission, index) {
SitePermissions.set(uri, permission, states[index % 2]);
});

Просмотреть файл

@ -24,7 +24,7 @@ function assertEditorBreakpoint(dbg, line) {
}
add_task(function*() {
requestLongerTimeout(2);
requestLongerTimeout(3);
const dbg = yield initDebugger("doc-scripts.html");
const { selectors: { getBreakpoints, getBreakpoint }, getState } = dbg;

Просмотреть файл

@ -927,11 +927,8 @@ GK_ATOM(onmozkeydownonplugin, "onmozkeydownonplugin")
GK_ATOM(onmozkeyuponplugin, "onmozkeyuponplugin")
GK_ATOM(onmozpointerlockchange, "onmozpointerlockchange")
GK_ATOM(onmozpointerlockerror, "onmozpointerlockerror")
GK_ATOM(onmoztimechange, "onmoztimechange")
GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll")
GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged")
GK_ATOM(onmoznetworkupload, "onmoznetworkupload")
GK_ATOM(onmoznetworkdownload, "onmoznetworkdownload")
GK_ATOM(onmapfolderlistingreq, "onmapfolderlistingreq")
GK_ATOM(onmapmessageslistingreq, "onmapmessageslistingreq")
GK_ATOM(onmapgetmessagereq, "onmapgetmessagereq")

Просмотреть файл

@ -257,10 +257,6 @@
#include "mozilla/dom/SpeechSynthesis.h"
#endif
#ifdef MOZ_B2G
#include "nsPISocketTransportService.h"
#endif
// Apple system headers seem to have a check() macro. <sigh>
#ifdef check
class nsIScriptTimeoutHandler;
@ -1622,10 +1618,6 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
mIdleRequestExecutor(nullptr),
#ifdef DEBUG
mSetOpenerWindowCalled(false),
#endif
#ifdef MOZ_B2G
mNetworkUploadObserverEnabled(false),
mNetworkDownloadObserverEnabled(false),
#endif
mCleanedUp(false),
mDialogAbuseCount(0),
@ -1971,11 +1963,6 @@ nsGlobalWindow::CleanUp()
sns->Unregister(mObserver);
}
#ifdef MOZ_B2G
DisableNetworkEvent(eNetworkUpload);
DisableNetworkEvent(eNetworkDownload);
#endif // MOZ_B2G
if (mIdleService) {
mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S);
}
@ -2047,9 +2034,6 @@ nsGlobalWindow::CleanUp()
DisableVRUpdates();
mHasVREvents = false;
mHasVRDisplayActivateEvents = false;
#ifdef MOZ_B2G
DisableTimeChangeNotifications();
#endif
DisableIdleCallbackRequests();
} else {
MOZ_ASSERT(!mHasGamepad);
@ -12168,27 +12152,6 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
return NS_OK;
}
#ifdef MOZ_B2G
if (!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) ||
!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC)) {
MOZ_ASSERT(IsInnerWindow());
if (!AsInner()->IsCurrentInnerWindow()) {
return NS_OK;
}
RefPtr<Event> event = NS_NewDOMEvent(this, nullptr, nullptr);
event->InitEvent(
!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC)
? NETWORK_UPLOAD_EVENT_NAME
: NETWORK_DOWNLOAD_EVENT_NAME,
false, false);
event->SetTrusted(true);
bool dummy;
return DispatchEvent(event, &dummy);
}
#endif // MOZ_B2G
if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
MOZ_ASSERT(!NS_strcmp(aData, u"intl.accept_languages"));
MOZ_ASSERT(IsInnerWindow());
@ -14667,80 +14630,6 @@ nsGlobalWindow::ReportLargeAllocStatus()
message);
}
#ifdef MOZ_B2G
void
nsGlobalWindow::EnableNetworkEvent(EventMessage aEventMessage)
{
MOZ_ASSERT(IsInnerWindow());
nsCOMPtr<nsIPermissionManager> permMgr =
services::GetPermissionManager();
if (!permMgr) {
NS_ERROR("No PermissionManager available!");
return;
}
uint32_t permission = nsIPermissionManager::DENY_ACTION;
permMgr->TestExactPermissionFromPrincipal(GetPrincipal(), "network-events",
&permission);
if (permission != nsIPermissionManager::ALLOW_ACTION) {
return;
}
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (!os) {
NS_ERROR("ObserverService should be available!");
return;
}
switch (aEventMessage) {
case eNetworkUpload:
if (!mNetworkUploadObserverEnabled) {
mNetworkUploadObserverEnabled = true;
os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC, false);
}
break;
case eNetworkDownload:
if (!mNetworkDownloadObserverEnabled) {
mNetworkDownloadObserverEnabled = true;
os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, false);
}
break;
default:
break;
}
}
void
nsGlobalWindow::DisableNetworkEvent(EventMessage aEventMessage)
{
MOZ_ASSERT(IsInnerWindow());
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (!os) {
return;
}
switch (aEventMessage) {
case eNetworkUpload:
if (mNetworkUploadObserverEnabled) {
mNetworkUploadObserverEnabled = false;
os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC);
}
break;
case eNetworkDownload:
if (mNetworkDownloadObserverEnabled) {
mNetworkDownloadObserverEnabled = false;
os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC);
}
break;
default:
break;
}
}
#endif // MOZ_B2G
void
nsGlobalWindow::RedefineProperty(JSContext* aCx, const char* aPropName,
JS::Handle<JS::Value> aValue,

Просмотреть файл

@ -653,13 +653,6 @@ public:
virtual void EnableTimeChangeNotifications() override;
virtual void DisableTimeChangeNotifications() override;
#ifdef MOZ_B2G
// Inner windows only.
virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) override;
virtual void DisableNetworkEvent(
mozilla::EventMessage aEventMessage) override;
#endif // MOZ_B2G
virtual nsresult SetArguments(nsIArray* aArguments) override;
void MaybeForgiveSpamCount();
@ -1977,11 +1970,6 @@ protected:
nsCOMPtr<nsIURI> mLastOpenedURI;
#endif
#ifdef MOZ_B2G
bool mNetworkUploadObserverEnabled;
bool mNetworkDownloadObserverEnabled;
#endif // MOZ_B2G
bool mCleanedUp;
nsCOMPtr<nsIDOMOfflineResourceList> mApplicationCache;

Просмотреть файл

@ -1687,21 +1687,21 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults)
u"CC(T+%.1f)[%s-%i] max pause: %lums, total time: %lums, slices: %lu, suspected: %lu, visited: %lu RCed and %lu%s GCed, collected: %lu RCed and %lu GCed (%lu|%lu|%lu waiting for GC)%s\n"
u"ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, max sync: %lu ms, removed: %lu";
nsString msg;
msg.Adopt(nsTextFormatter::smprintf(kFmt, double(delta) / PR_USEC_PER_SEC,
ProcessNameForCollectorLog(), getpid(),
gCCStats.mMaxSliceTime, gCCStats.mTotalSliceTime,
aResults.mNumSlices, gCCStats.mSuspected,
aResults.mVisitedRefCounted, aResults.mVisitedGCed, mergeMsg.get(),
aResults.mFreedRefCounted, aResults.mFreedGCed,
sCCollectedWaitingForGC, sCCollectedZonesWaitingForGC, sLikelyShortLivingObjectsNeedingGC,
gcMsg.get(),
sForgetSkippableBeforeCC,
minForgetSkippableTime / PR_USEC_PER_MSEC,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
(sTotalForgetSkippableTime / cleanups) /
PR_USEC_PER_MSEC,
sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
gCCStats.mMaxSkippableDuration, sRemovedPurples));
nsTextFormatter::ssprintf(msg, kFmt, double(delta) / PR_USEC_PER_SEC,
ProcessNameForCollectorLog(), getpid(),
gCCStats.mMaxSliceTime, gCCStats.mTotalSliceTime,
aResults.mNumSlices, gCCStats.mSuspected,
aResults.mVisitedRefCounted, aResults.mVisitedGCed, mergeMsg.get(),
aResults.mFreedRefCounted, aResults.mFreedGCed,
sCCollectedWaitingForGC, sCCollectedZonesWaitingForGC, sLikelyShortLivingObjectsNeedingGC,
gcMsg.get(),
sForgetSkippableBeforeCC,
minForgetSkippableTime / PR_USEC_PER_MSEC,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
(sTotalForgetSkippableTime / cleanups) /
PR_USEC_PER_MSEC,
sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
gCCStats.mMaxSkippableDuration, sRemovedPurples);
if (sPostGCEventsToConsole) {
nsCOMPtr<nsIConsoleService> cs =
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
@ -1741,27 +1741,27 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults)
u"\"total\": %lu, "
u"\"removed\": %lu } "
u"}";
nsString json;
json.Adopt(nsTextFormatter::smprintf(kJSONFmt, PR_Now(), ccNowDuration,
gCCStats.mMaxSliceTime,
gCCStats.mTotalSliceTime,
gCCStats.mMaxGCDuration,
gCCStats.mMaxSkippableDuration,
gCCStats.mSuspected,
aResults.mVisitedRefCounted, aResults.mVisitedGCed,
aResults.mFreedRefCounted, aResults.mFreedGCed,
sCCollectedWaitingForGC,
sCCollectedZonesWaitingForGC,
sLikelyShortLivingObjectsNeedingGC,
aResults.mForcedGC,
sForgetSkippableBeforeCC,
minForgetSkippableTime / PR_USEC_PER_MSEC,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
(sTotalForgetSkippableTime / cleanups) /
PR_USEC_PER_MSEC,
sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
sRemovedPurples));
nsString json;
nsTextFormatter::ssprintf(json, kJSONFmt, PR_Now(), ccNowDuration,
gCCStats.mMaxSliceTime,
gCCStats.mTotalSliceTime,
gCCStats.mMaxGCDuration,
gCCStats.mMaxSkippableDuration,
gCCStats.mSuspected,
aResults.mVisitedRefCounted, aResults.mVisitedGCed,
aResults.mFreedRefCounted, aResults.mFreedGCed,
sCCollectedWaitingForGC,
sCCollectedZonesWaitingForGC,
sLikelyShortLivingObjectsNeedingGC,
aResults.mForcedGC,
sForgetSkippableBeforeCC,
minForgetSkippableTime / PR_USEC_PER_MSEC,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
(sTotalForgetSkippableTime / cleanups) /
PR_USEC_PER_MSEC,
sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
sRemovedPurples);
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
if (observerService) {
observerService->NotifyObservers(nullptr, "cycle-collection-statistics", json.get());
@ -2253,12 +2253,12 @@ DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress, const JS::GCDescrip
PRTime delta = GetCollectionTimeDelta();
if (sPostGCEventsToConsole) {
nsString prefix, gcstats;
nsString gcstats;
gcstats.Adopt(aDesc.formatSummaryMessage(aCx));
prefix.Adopt(nsTextFormatter::smprintf(u"GC(T+%.1f)[%s-%i] ",
double(delta) / PR_USEC_PER_SEC,
ProcessNameForCollectorLog(),
getpid()));
nsAutoString prefix;
nsTextFormatter::ssprintf(prefix, u"GC(T+%.1f)[%s-%i] ",
double(delta) / PR_USEC_PER_SEC,
ProcessNameForCollectorLog(), getpid());
nsString msg = prefix + gcstats;
nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (cs) {
@ -2339,11 +2339,11 @@ DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress, const JS::GCDescrip
}
if (sPostGCEventsToConsole) {
nsString prefix, gcstats;
nsString gcstats;
gcstats.Adopt(aDesc.formatSliceMessage(aCx));
prefix.Adopt(nsTextFormatter::smprintf(u"[%s-%i] ",
ProcessNameForCollectorLog(),
getpid()));
nsAutoString prefix;
nsTextFormatter::ssprintf(prefix, u"[%s-%i] ",
ProcessNameForCollectorLog(), getpid());
nsString msg = prefix + gcstats;
nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (cs) {

Просмотреть файл

@ -493,24 +493,6 @@ public:
virtual void EnableTimeChangeNotifications() = 0;
virtual void DisableTimeChangeNotifications() = 0;
#ifdef MOZ_B2G
/**
* Tell the window that it should start to listen to the network event of the
* given aType.
*
* Inner windows only.
*/
virtual void EnableNetworkEvent(mozilla::EventMessage aEventMessage) = 0;
/**
* Tell the window that it should stop to listen to the network event of the
* given aType.
*
* Inner windows only.
*/
virtual void DisableNetworkEvent(mozilla::EventMessage aEventMessage) = 0;
#endif // MOZ_B2G
/**
* Tell this window that there is an observer for gamepad input
*

Просмотреть файл

@ -13,9 +13,6 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/EventListenerManager.h"
#ifdef MOZ_B2G
#include "mozilla/Hal.h"
#endif // #ifdef MOZ_B2G
#include "mozilla/HalSensor.h"
#include "mozilla/InternalMutationEvent.h"
#include "mozilla/JSEventHandler.h"
@ -350,14 +347,6 @@ EventListenerManager::AddEventListenerInternal(
} else if (aTypeAtom == nsGkAtoms::onorientationchange) {
EnableDevice(eOrientationChange);
#endif
#ifdef MOZ_B2G
} else if (aTypeAtom == nsGkAtoms::onmoztimechange) {
EnableDevice(eTimeChange);
} else if (aTypeAtom == nsGkAtoms::onmoznetworkupload) {
EnableDevice(eNetworkUpload);
} else if (aTypeAtom == nsGkAtoms::onmoznetworkdownload) {
EnableDevice(eNetworkDownload);
#endif // MOZ_B2G
} else if (aTypeAtom == nsGkAtoms::ontouchstart ||
aTypeAtom == nsGkAtoms::ontouchend ||
aTypeAtom == nsGkAtoms::ontouchmove ||
@ -492,11 +481,6 @@ EventListenerManager::IsDeviceType(EventMessage aEventMessage)
case eUserProximity:
#if defined(MOZ_WIDGET_ANDROID)
case eOrientationChange:
#endif
#ifdef MOZ_B2G
case eTimeChange:
case eNetworkUpload:
case eNetworkDownload:
#endif
return true;
default:
@ -548,15 +532,6 @@ EventListenerManager::EnableDevice(EventMessage aEventMessage)
case eOrientationChange:
window->EnableOrientationChangeListener();
break;
#endif
#ifdef MOZ_B2G
case eTimeChange:
window->EnableTimeChangeNotifications();
break;
case eNetworkUpload:
case eNetworkDownload:
window->EnableNetworkEvent(aEventMessage);
break;
#endif
default:
NS_WARNING("Enabling an unknown device sensor.");
@ -604,15 +579,6 @@ EventListenerManager::DisableDevice(EventMessage aEventMessage)
window->DisableOrientationChangeListener();
break;
#endif
#ifdef MOZ_B2G
case eTimeChange:
window->DisableTimeChangeNotifications();
break;
case eNetworkUpload:
case eNetworkDownload:
window->DisableNetworkEvent(aEventMessage);
break;
#endif // MOZ_B2G
default:
NS_WARNING("Disabling an unknown device sensor.");
break;

Просмотреть файл

@ -642,21 +642,6 @@ WINDOW_ONLY_EVENT(appinstalled,
eBasicEventClass)
#ifdef MOZ_B2G
WINDOW_ONLY_EVENT(moztimechange,
eTimeChange,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(moznetworkupload,
eNetworkUpload,
EventNameType_None,
eBasicEventClass)
WINDOW_ONLY_EVENT(moznetworkdownload,
eNetworkDownload,
EventNameType_None,
eBasicEventClass)
#endif // MOZ_B2G
TOUCH_EVENT(touchstart,
eTouchStart,
EventNameType_All,

Просмотреть файл

@ -32,10 +32,6 @@ DEFINE_KEYNAME_INTERNAL(PrintableKey, "MozPrintableKey")
DEFINE_KEYNAME_INTERNAL(SoftLeft, "MozSoftLeft")
DEFINE_KEYNAME_INTERNAL(SoftRight, "MozSoftRight")
#ifdef MOZ_B2G
DEFINE_KEYNAME_INTERNAL(HomeScreen, "MozHomeScreen")
#endif // #ifdef MOZ_B2G
/******************************************************************************
* Modifier Keys
*****************************************************************************/

Просмотреть файл

@ -203,7 +203,7 @@ TouchEvent::PrefEnabled(nsIDocShell* aDocShell)
enabled = false;
} else {
if (sPrefCacheValue == 2) {
#if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID)
#if defined(MOZ_WIDGET_ANDROID)
// Touch support is always enabled on B2G and android.
enabled = true;
#elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3

Просмотреть файл

@ -8,6 +8,8 @@
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
var isWindows = (getPlatform() == "windows");
var apz_touch_action_prefs = [
// Obviously we need touch-action support enabled for testing touch-action.
["layout.css.touch_action.enabled", true],
@ -30,6 +32,7 @@ var apz_touch_action_prefs = [
// position is synced back to the main thread. So we disable displayport
// expiry for these tests.
["apz.displayport_expiry_ms", 0],
["apz.test.fails_with_native_injection", isWindows],
];
function apzScriptInjector(name) {

Просмотреть файл

@ -1025,13 +1025,6 @@ UploadLastDir::FetchDirectoryAndDisplayPicker(nsIDocument* aDoc,
nsCOMPtr<nsIContentPrefCallback2> prefCallback =
new UploadLastDir::ContentPrefCallback(aFilePicker, aFpCallback);
#ifdef MOZ_B2G
if (XRE_IsContentProcess()) {
prefCallback->HandleCompletion(nsIContentPrefCallback2::COMPLETE_ERROR);
return NS_OK;
}
#endif
// Attempt to get the CPS, if it's not present we'll fallback to use the Desktop folder
nsCOMPtr<nsIContentPrefService2> contentPrefService =
do_GetService(NS_CONTENT_PREF_SERVICE_CONTRACTID);
@ -1056,12 +1049,6 @@ UploadLastDir::StoreLastUsedDirectory(nsIDocument* aDoc, nsIFile* aDir)
return NS_OK;
}
#ifdef MOZ_B2G
if (XRE_IsContentProcess()) {
return NS_OK;
}
#endif
nsCOMPtr<nsIURI> docURI = aDoc->GetDocumentURI();
NS_PRECONDITION(docURI, "docURI is null");
@ -5921,7 +5908,7 @@ HTMLInputElement::ChooseDirectory(ErrorResult& aRv)
// "Pick Folder..." button on platforms that don't have a directory picker
// we have to redirect to the file picker here.
InitFilePicker(
#if defined(ANDROID) || defined(MOZ_B2G)
#if defined(ANDROID)
// No native directory picker - redirect to plain file picker
FILE_PICKER_FILE
#else

Просмотреть файл

@ -802,10 +802,10 @@ nsTextInputSelectionImpl::CheckVisibilityContent(nsIContent* aNode,
return shell->CheckVisibilityContent(aNode, aStartOffset, aEndOffset, aRetval);
}
class nsTextInputListener : public nsISelectionListener,
public nsIDOMEventListener,
public nsIEditorObserver,
public nsSupportsWeakReference
class nsTextInputListener final : public nsISelectionListener,
public nsIDOMEventListener,
public nsIEditorObserver,
public nsSupportsWeakReference
{
public:
/** the default constructor
@ -820,6 +820,10 @@ public:
void SettingValue(bool aValue) { mSettingValue = aValue; }
void SetValueChanged(bool aSetValueChanged) { mSetValueChanged = aSetValueChanged; }
// aFrame is an optional pointer to our frame, if not passed the method will
// use mFrame to compute it lazily.
void HandleValueChanged(nsTextControlFrame* aFrame = nullptr);
NS_DECL_ISUPPORTS
NS_DECL_NSISELECTIONLISTENER
@ -1082,18 +1086,29 @@ nsTextInputListener::EditAction()
return NS_OK;
}
HandleValueChanged(frame);
return NS_OK;
}
void
nsTextInputListener::HandleValueChanged(nsTextControlFrame* aFrame)
{
// Make sure we know we were changed (do NOT set this to false if there are
// no undo items; JS could change the value and we'd still need to save it)
if (mSetValueChanged) {
frame->SetValueChanged(true);
if (!aFrame) {
nsITextControlFrame* frameBase = do_QueryFrame(mFrame);
aFrame = static_cast<nsTextControlFrame*> (frameBase);
NS_ASSERTION(aFrame, "Where is our frame?");
}
aFrame->SetValueChanged(true);
}
if (!mSettingValue) {
mTxtCtrlElement->OnValueChanged(/* aNotify = */ true,
/* aWasInteractiveUserChange = */ true);
}
return NS_OK;
}
NS_IMETHODIMP
@ -2684,6 +2699,11 @@ nsTextEditorState::SetValue(const nsAString& aValue, const nsAString* aOldValue,
}
textEditor->SetText(newValue);
// Call the listener's HandleValueChanged() callback manually, since
// we don't use the transaction manager in this path and it could be
// that the editor would bypass calling the listener for that reason.
mTextListener->HandleValueChanged();
}
mTextListener->SetValueChanged(true);

Просмотреть файл

@ -35,7 +35,9 @@ addLoadEvent(function () {
SpecialPowers.pushPrefEnv({
"set": [
["full-screen-api.unprefix.enabled", true],
["full-screen-api.allow-trusted-requests-only", false]
["full-screen-api.allow-trusted-requests-only", false],
// Use legacy data: URI behavior to run test.
["security.data_uri.unique_opaque_origin", false]
]
}, next);
});

Просмотреть файл

@ -3647,8 +3647,6 @@ UpgradeSchemaFrom18_0To19_0(mozIStorageConnection* aConnection)
return NS_OK;
}
#if !defined(MOZ_B2G)
class NormalJSContext;
class UpgradeFileIdsFunction final
@ -3684,8 +3682,6 @@ private:
nsIVariant** aResult) override;
};
#endif // MOZ_B2G
nsresult
UpgradeSchemaFrom19_0To20_0(nsIFile* aFMDirectory,
mozIStorageConnection* aConnection)
@ -3695,20 +3691,6 @@ UpgradeSchemaFrom19_0To20_0(nsIFile* aFMDirectory,
AUTO_PROFILER_LABEL("UpgradeSchemaFrom19_0To20_0", STORAGE);
#if defined(MOZ_B2G)
// We don't have to do the upgrade of file ids on B2G. The old format was
// only used by the previous single process implementation and B2G was
// always multi process. This is a nice optimization since the upgrade needs
// to deserialize all structured clones which reference a stored file or
// a mutable file.
nsresult rv = aConnection->SetSchemaVersion(MakeSchemaVersion(20, 0));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
#else // MOZ_B2G
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING(
"SELECT count(*) "
@ -3807,8 +3789,6 @@ UpgradeSchemaFrom19_0To20_0(nsIFile* aFMDirectory,
return rv;
}
#endif // MOZ_B2G
return NS_OK;
}
@ -19546,8 +19526,6 @@ NS_IMPL_ISUPPORTS(CompressDataBlobsFunction, mozIStorageFunction)
NS_IMPL_ISUPPORTS(EncodeKeysFunction, mozIStorageFunction)
NS_IMPL_ISUPPORTS(StripObsoleteOriginAttributesFunction, mozIStorageFunction);
#if !defined(MOZ_B2G)
nsresult
UpgradeFileIdsFunction::Init(nsIFile* aFMDirectory,
mozIStorageConnection* aConnection)
@ -19639,8 +19617,6 @@ UpgradeFileIdsFunction::OnFunctionCall(mozIStorageValueArray* aArguments,
return NS_OK;
}
#endif // MOZ_B2G
// static
void
DatabaseOperationBase::GetBindingClauseForKeyRange(

Просмотреть файл

@ -804,8 +804,6 @@ public:
// We don't need to upgrade database on B2G. See the comment in ActorsParent.cpp,
// UpgradeSchemaFrom18_0To19_0()
#if !defined(MOZ_B2G)
class UpgradeDeserializationHelper
{
public:
@ -872,8 +870,6 @@ public:
}
};
#endif // MOZ_B2G
template <class Traits>
JSObject*
CommonStructuredCloneReadCallback(JSContext* aCx,
@ -1214,8 +1210,6 @@ IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
return true;
}
#if !defined(MOZ_B2G)
// static
bool
IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
@ -1252,8 +1246,6 @@ IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
return true;
}
#endif // MOZ_B2G
#ifdef DEBUG
void

Просмотреть файл

@ -101,12 +101,10 @@ public:
StructuredCloneReadInfo& aCloneReadInfo,
JS::MutableHandle<JS::Value> aValue);
#if !defined(MOZ_B2G)
static bool
DeserializeUpgradeValue(JSContext* aCx,
StructuredCloneReadInfo& aCloneReadInfo,
JS::MutableHandle<JS::Value> aValue);
#endif
static const JSClass*
DummyPropClass()

Просмотреть файл

@ -35,8 +35,6 @@
#include "mozilla/dom/MemoryReportRequest.h"
#include "mozilla/dom/ProcessGlobal.h"
#include "mozilla/dom/PushNotifier.h"
#include "mozilla/dom/LocalStorage.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/dom/TabGroup.h"
#include "mozilla/dom/workers/ServiceWorkerManager.h"
#include "mozilla/dom/nsIContentChild.h"
@ -2105,21 +2103,6 @@ ContentChild::DeallocPMediaChild(media::PMediaChild *aActor)
return media::DeallocPMediaChild(aActor);
}
PStorageChild*
ContentChild::AllocPStorageChild()
{
MOZ_CRASH("We should never be manually allocating PStorageChild actors");
return nullptr;
}
bool
ContentChild::DeallocPStorageChild(PStorageChild* aActor)
{
StorageDBChild* child = static_cast<StorageDBChild*>(aActor);
child->ReleaseIPDLReference();
return true;
}
PSpeechSynthesisChild*
ContentChild::AllocPSpeechSynthesisChild()
{
@ -2317,7 +2300,7 @@ ContentChild::ProcessingError(Result aCode, const char* aReason)
MOZ_CRASH("not reached");
}
#if defined(MOZ_CRASHREPORTER) && !defined(MOZ_B2G)
#if defined(MOZ_CRASHREPORTER)
nsDependentCString reason(aReason);
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ipc_channel_error"), reason);
#endif
@ -3247,19 +3230,6 @@ ContentChild::RecvBlobURLUnregistration(const nsCString& aURI)
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentChild::RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const IPC::Principal& aPrincipal,
const bool& aIsPrivate)
{
LocalStorage::DispatchStorageEvent(aDocumentURI, aKey, aOldValue, aNewValue,
aPrincipal, aIsPrivate, nullptr, true);
return IPC_OK();
}
#if defined(XP_WIN) && defined(ACCESSIBILITY)
bool
ContentChild::SendGetA11yContentId()

Просмотреть файл

@ -49,7 +49,6 @@ namespace dom {
class AlertObserver;
class ConsoleListener;
class PStorageChild;
class ClonedMessageData;
class TabChild;
class GetFilesHelperChild;
@ -300,10 +299,6 @@ public:
virtual bool DeallocPMediaChild(PMediaChild* aActor) override;
virtual PStorageChild* AllocPStorageChild() override;
virtual bool DeallocPStorageChild(PStorageChild* aActor) override;
virtual PPresentationChild* AllocPPresentationChild() override;
virtual bool DeallocPPresentationChild(PPresentationChild* aActor) override;
@ -414,14 +409,6 @@ public:
virtual mozilla::ipc::IPCResult
RecvInitBlobURLs(nsTArray<BlobURLRegistrationData>&& aRegistations) override;
virtual mozilla::ipc::IPCResult
RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const IPC::Principal& aPrincipal,
const bool& aIsPrivate) override;
virtual mozilla::ipc::IPCResult RecvLastPrivateDocShellDestroyed() override;
virtual mozilla::ipc::IPCResult

Просмотреть файл

@ -48,8 +48,6 @@
#include "mozilla/dom/PContentPermissionRequestParent.h"
#include "mozilla/dom/PCycleCollectWithLogsParent.h"
#include "mozilla/dom/ServiceWorkerRegistrar.h"
#include "mozilla/dom/Storage.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/dom/power/PowerManagerService.h"
#include "mozilla/dom/Permissions.h"
#include "mozilla/dom/PresentationParent.h"
@ -2100,12 +2098,10 @@ ContentParent::ContentParent(ContentParent* aOpener,
if (XRE_IsParentProcess()) {
audio::AudioNotificationSender::Init();
}
#if !defined(MOZ_B2G)
// Request Windows message deferral behavior on our side of the PContent
// channel. Generally only applies to the situation where we get caught in
// a deadlock with the plugin process when sending CPOWs.
GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
#endif
#endif
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
@ -2934,7 +2930,7 @@ ContentParent::KillHard(const char* aReason)
mCalledKillHard = true;
mForceKillTimer = nullptr;
#if defined(MOZ_CRASHREPORTER) && !defined(MOZ_B2G)
#if defined(MOZ_CRASHREPORTER)
// We're about to kill the child process associated with this content.
// Something has gone wrong to get us here, so we generate a minidump
// of the parent and child for submission to the crash server.
@ -2974,7 +2970,7 @@ ContentParent::KillHard(const char* aReason)
void
ContentParent::OnGenerateMinidumpComplete(bool aDumpResult)
{
#if defined(MOZ_CRASHREPORTER) && !defined(MOZ_B2G)
#if defined(MOZ_CRASHREPORTER)
if (mCrashReporter && aDumpResult) {
// CrashReporterHost::GenerateMinidumpAndPair() is successful.
mCreatedPairedMinidumps = mCrashReporter->FinalizeCrashReport();
@ -3304,20 +3300,6 @@ ContentParent::DeallocPMediaParent(media::PMediaParent *aActor)
return media::DeallocPMediaParent(aActor);
}
PStorageParent*
ContentParent::AllocPStorageParent()
{
return new StorageDBParent();
}
bool
ContentParent::DeallocPStorageParent(PStorageParent* aActor)
{
StorageDBParent* child = static_cast<StorageDBParent*>(aActor);
child->ReleaseIPDLReference();
return true;
}
PPresentationParent*
ContentParent::AllocPPresentationParent()
{
@ -4962,25 +4944,6 @@ ContentParent::RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aUR
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentParent::RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const Principal& aPrincipal,
const bool& aIsPrivate)
{
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
if (cp != this) {
Unused << cp->SendDispatchLocalStorageChange(
nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
}
}
return IPC_OK();
}
mozilla::ipc::IPCResult
ContentParent::RecvGetA11yContentId(uint32_t* aContentId)
{

Просмотреть файл

@ -97,7 +97,6 @@ namespace dom {
class Element;
class TabParent;
class PStorageParent;
class ClonedMessageData;
class MemoryReport;
class TabContext;
@ -449,13 +448,6 @@ public:
virtual PHeapSnapshotTempFileHelperParent*
AllocPHeapSnapshotTempFileHelperParent() override;
virtual PStorageParent* AllocPStorageParent() override;
virtual mozilla::ipc::IPCResult RecvPStorageConstructor(PStorageParent* aActor) override
{
return PContentParent::RecvPStorageConstructor(aActor);
}
virtual PJavaScriptParent*
AllocPJavaScriptParent() override;
@ -566,14 +558,6 @@ public:
virtual mozilla::ipc::IPCResult
RecvUnstoreAndBroadcastBlobURLUnregistration(const nsCString& aURI) override;
virtual mozilla::ipc::IPCResult
RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const IPC::Principal& aPrincipal,
const bool& aIsPrivate) override;
virtual mozilla::ipc::IPCResult
RecvGetA11yContentId(uint32_t* aContentId) override;
@ -931,8 +915,6 @@ private:
virtual bool DeallocPMediaParent(PMediaParent* aActor) override;
virtual bool DeallocPStorageParent(PStorageParent* aActor) override;
virtual PPresentationParent* AllocPPresentationParent() override;
virtual bool DeallocPPresentationParent(PPresentationParent* aActor) override;

Просмотреть файл

@ -31,7 +31,6 @@ include protocol PParentToChildStream;
include protocol POfflineCacheUpdate;
include protocol PRenderFrame;
include protocol PSpeechSynthesis;
include protocol PStorage;
include protocol PTestShell;
include protocol PJavaScript;
include protocol PRemoteSpellcheckEngine;
@ -291,7 +290,6 @@ nested(upto inside_cpow) sync protocol PContent
manages PChildToParentStream;
manages PParentToChildStream;
manages PSpeechSynthesis;
manages PStorage;
manages PTestShell;
manages PJavaScript;
manages PRemoteSpellcheckEngine;
@ -566,13 +564,6 @@ child:
async BlobURLUnregistration(nsCString aURI);
async DispatchLocalStorageChange(nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue,
Principal principal,
bool isPrivate);
async GMPsChanged(GMPCapabilityData[] capabilities);
@ -713,8 +704,6 @@ parent:
async PSpeechSynthesis();
nested(inside_cpow) async PStorage();
async PMedia();
async PWebrtcGlobal();
@ -1048,13 +1037,6 @@ parent:
async UnstoreAndBroadcastBlobURLUnregistration(nsCString url);
async BroadcastLocalStorageChange(nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue,
Principal principal,
bool isPrivate);
/**
* Messages for communicating child Telemetry to the parent process
*/

Просмотреть файл

@ -246,10 +246,6 @@ MaybeInvalidTabContext::MaybeInvalidTabContext(const IPCTabContext& aParams)
// It is meant as a temporary solution until service workers can
// provide a TabChild equivalent. Don't allow this on b2g since
// it might be used to escalate privileges.
#ifdef MOZ_B2G
mInvalidReason = "ServiceWorkerClients::OpenWindow is not supported.";
return;
#endif
if (!Preferences::GetBool("dom.serviceWorkers.enabled", false)) {
mInvalidReason = "ServiceWorkers should be enabled.";
return;

Просмотреть файл

@ -126,7 +126,6 @@ LOCAL_INCLUDES += [
'/dom/geolocation',
'/dom/media/webspeech/synth/ipc',
'/dom/security',
'/dom/storage',
'/dom/workers',
'/extensions/cookie',
'/extensions/spellcheck/src',

Просмотреть файл

@ -347,17 +347,9 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aChannelMap, uint32_t aRate,
params.channels = mOutChannels;
params.layout = CubebUtils::ConvertChannelMapToCubebLayout(aChannelMap);
#if defined(__ANDROID__)
#if defined(MOZ_B2G)
params.stream_type = CubebUtils::ConvertChannelToCubebType(aAudioChannel);
#else
params.stream_type = CUBEB_STREAM_TYPE_MUSIC;
#endif
if (params.stream_type == CUBEB_STREAM_TYPE_MAX) {
return NS_ERROR_INVALID_ARG;
}
#endif
params.format = ToCubebFormat<AUDIO_OUTPUT_FORMAT>::value;
mAudioClock.Init(aRate);

Просмотреть файл

@ -491,33 +491,6 @@ cubeb_channel_layout ConvertChannelMapToCubebLayout(uint32_t aChannelMap)
}
}
#if defined(__ANDROID__) && defined(MOZ_B2G)
cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel)
{
switch(aChannel) {
case dom::AudioChannel::Normal:
/* FALLTHROUGH */
case dom::AudioChannel::Content:
return CUBEB_STREAM_TYPE_MUSIC;
case dom::AudioChannel::Notification:
return CUBEB_STREAM_TYPE_NOTIFICATION;
case dom::AudioChannel::Alarm:
return CUBEB_STREAM_TYPE_ALARM;
case dom::AudioChannel::Telephony:
return CUBEB_STREAM_TYPE_VOICE_CALL;
case dom::AudioChannel::Ringer:
return CUBEB_STREAM_TYPE_RING;
case dom::AudioChannel::System:
return CUBEB_STREAM_TYPE_SYSTEM;
case dom::AudioChannel::Publicnotification:
return CUBEB_STREAM_TYPE_SYSTEM_ENFORCED;
default:
NS_ERROR("The value of AudioChannel is invalid");
return CUBEB_STREAM_TYPE_MAX;
}
}
#endif
void GetCurrentBackend(nsAString& aBackend)
{
cubeb* cubebContext = GetCubebContext();

Просмотреть файл

@ -50,9 +50,6 @@ uint32_t GetCubebPlaybackLatencyInMilliseconds();
Maybe<uint32_t> GetCubebMSGLatencyInFrames();
bool CubebLatencyPrefSet();
cubeb_channel_layout ConvertChannelMapToCubebLayout(uint32_t aChannelMap);
#if defined(__ANDROID__) && defined(MOZ_B2G)
cubeb_stream_type ConvertChannelToCubebType(dom::AudioChannel aChannel);
#endif
void GetCurrentBackend(nsAString& aBackend);
void GetPreferredChannelLayout(nsAString& aLayout);
void GetDeviceCollection(nsTArray<RefPtr<AudioDeviceInfo>>& aDeviceInfos,

Просмотреть файл

@ -628,15 +628,7 @@ AudioCallbackDriver::Init()
mSampleRate = output.rate = CubebUtils::PreferredSampleRate();
#if defined(__ANDROID__)
#if defined(MOZ_B2G)
output.stream_type = CubebUtils::ConvertChannelToCubebType(mAudioChannel);
#else
output.stream_type = CUBEB_STREAM_TYPE_MUSIC;
#endif
if (output.stream_type == CUBEB_STREAM_TYPE_MAX) {
NS_WARNING("Bad stream type");
return false;
}
#else
(void)mAudioChannel;
#endif

Просмотреть файл

@ -69,10 +69,6 @@
#include "browser_logging/WebRtcLog.h"
#endif
#ifdef MOZ_B2G
#include "MediaPermissionGonk.h"
#endif
#if defined (XP_WIN)
#include "mozilla/WindowsVersion.h"
#include <winsock2.h>
@ -1937,10 +1933,6 @@ MediaManager::Get() {
__LINE__,
NS_LITERAL_STRING("Media shutdown"));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
#ifdef MOZ_B2G
// Init MediaPermissionManager before sending out any permission requests.
(void) MediaPermissionManager::GetInstance();
#endif //MOZ_B2G
}
return sSingleton;
}

Просмотреть файл

@ -828,7 +828,7 @@ class RTCPeerConnection {
async _getPermission() {
if (!this._havePermission) {
let privileged = this._isChrome || AppConstants.MOZ_B2G ||
let privileged = this._isChrome ||
Services.prefs.getBoolPref("media.navigator.permission.disabled");
if (privileged) {

Просмотреть файл

@ -55,11 +55,8 @@ public:
static const int DEFAULT_169_VIDEO_WIDTH = 1280;
static const int DEFAULT_169_VIDEO_HEIGHT = 720;
#ifndef MOZ_B2G
static const int DEFAULT_SAMPLE_RATE = 32000;
#else
static const int DEFAULT_SAMPLE_RATE = 16000;
#endif
// This allows using whatever rate the graph is using for the
// MediaStreamTrack. This is useful for microphone data, we know it's already
// at the correct rate for insertion in the MSG.

Просмотреть файл

@ -814,7 +814,6 @@ MediaEngineWebRTCMicrophoneSource::AllocChannel()
// Check for availability.
if (!mAudioInput->SetRecordingDevice(mCapIndex)) {
#ifndef MOZ_B2G
// Because of the permission mechanism of B2G, we need to skip the status
// check here.
bool avail = false;
@ -825,7 +824,6 @@ MediaEngineWebRTCMicrophoneSource::AllocChannel()
}
return false;
}
#endif // MOZ_B2G
// Set "codec" to PCM, 32kHz on device's channels
ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine));

Просмотреть файл

@ -16,42 +16,6 @@ typedef mozilla::dom::Sequence<nsString> WebrtcGlobalLog;
namespace IPC {
template<typename T>
struct ParamTraits<mozilla::dom::Optional<T>>
{
typedef mozilla::dom::Optional<T> paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
if (aParam.WasPassed()) {
WriteParam(aMsg, true);
WriteParam(aMsg, aParam.Value());
return;
}
WriteParam(aMsg, false);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
bool was_passed = false;
if (!ReadParam(aMsg, aIter, &was_passed)) {
return false;
}
aResult->Reset(); //XXX Optional_base seems to reach this point with isSome true.
if (was_passed) {
if (!ReadParam(aMsg, aIter, &(aResult->Construct()))) {
return false;
}
}
return true;
}
};
template<typename T>
struct ParamTraits<mozilla::dom::Sequence<T>>
{

Просмотреть файл

@ -159,10 +159,6 @@ class AlertServiceObserver: public nsIObserver
// forward to parent
if (mNotification) {
#ifdef MOZ_B2G
if (NS_FAILED(mNotification->CheckInnerWindowCorrectness()))
return NS_ERROR_NOT_AVAILABLE;
#endif
mNotification->HandleAlertServiceNotification(aTopic);
}
return NS_OK;

Просмотреть файл

@ -10,6 +10,7 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/OriginAttributes.h"
namespace IPC {
@ -21,6 +22,30 @@ struct ParamTraits<mozilla::dom::quota::PersistenceType> :
mozilla::dom::quota::PERSISTENCE_TYPE_INVALID>
{ };
template <>
struct ParamTraits<mozilla::OriginAttributesPattern>
{
typedef mozilla::OriginAttributesPattern paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mAppId);
WriteParam(aMsg, aParam.mFirstPartyDomain);
WriteParam(aMsg, aParam.mInIsolatedMozBrowser);
WriteParam(aMsg, aParam.mPrivateBrowsingId);
WriteParam(aMsg, aParam.mUserContextId);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
return ReadParam(aMsg, aIter, &aResult->mAppId) &&
ReadParam(aMsg, aIter, &aResult->mFirstPartyDomain) &&
ReadParam(aMsg, aIter, &aResult->mInIsolatedMozBrowser) &&
ReadParam(aMsg, aIter, &aResult->mPrivateBrowsingId) &&
ReadParam(aMsg, aIter, &aResult->mUserContextId);
}
};
} // namespace IPC
#endif // mozilla_dom_quota_SerializationHelpers_h

Просмотреть файл

@ -868,15 +868,6 @@ nsCSPContext::SendReports(nsISupports* aBlockedContentSource,
{
NS_ENSURE_ARG_MAX(aViolatedPolicyIndex, mPolicies.Length() - 1);
#ifdef MOZ_B2G
// load group information (on process-split necko implementations like b2g).
// (fix this in bug 1011086)
if (!mCallingChannelLoadGroup) {
NS_WARNING("Load group required but not present for report sending; cannot send CSP violation reports");
return NS_ERROR_FAILURE;
}
#endif
dom::CSPReport report;
nsresult rv;

Просмотреть файл

@ -13,8 +13,10 @@
var frame = document.getElementById("dataFrame");
var principal = SpecialPowers.wrap(frame.contentDocument).nodePrincipal;
var cspJSON = principal.cspJSON;
var result = principal.cspJSON ? "dataInheritsCSP" : "dataDoesNotInheritCSP";
window.parent.postMessage({result}, "*");
var cspOBJ = JSON.parse(principal.cspJSON);
// make sure we got >>one<< policy
var policies = cspOBJ["csp-policies"];
window.parent.postMessage({result: policies.length}, "*");
</script>
</body>

Просмотреть файл

@ -22,7 +22,9 @@ SimpleTest.waitForExplicitFinish();
window.addEventListener("message", receiveMessage);
function receiveMessage(event) {
window.removeEventListener("message", receiveMessage);
is(event.data.result, "dataInheritsCSP",
// toplevel CSP should apply to data: URI iframe hence resulting
// in 1 applied policy.
is(event.data.result, 1,
"data: URI iframe inherits CSP from including context");
SimpleTest.finish();
}

Просмотреть файл

@ -21,6 +21,8 @@
#include "mozilla/dom/StorageBinding.h"
#include "mozilla/dom/StorageEvent.h"
#include "mozilla/dom/StorageEventBinding.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/Services.h"
#include "mozilla/Preferences.h"
#include "mozilla/EnumSet.h"
@ -179,13 +181,20 @@ LocalStorage::BroadcastChangeNotification(const nsAString& aKey,
const nsAString& aOldValue,
const nsAString& aNewValue)
{
if (!XRE_IsParentProcess() && Principal()) {
// If we are in a child process, we want to send a message to the parent in
// order to broadcast the StorageEvent correctly to any child process.
dom::ContentChild* cc = dom::ContentChild::GetSingleton();
Unused << NS_WARN_IF(!cc->SendBroadcastLocalStorageChange(
mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
IPC::Principal(Principal()), mIsPrivate));
if (Principal()) {
// We want to send a message to the parent in order to broadcast the
// StorageEvent correctly to any child process.
PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
MOZ_ASSERT(actor);
PrincipalInfo principalInfo;
nsresult rv = PrincipalToPrincipalInfo(Principal(), &principalInfo);
if (!NS_WARN_IF(NS_FAILED(rv))) {
Unused << NS_WARN_IF(!actor->SendBroadcastLocalStorageChange(
mDocumentURI, nsString(aKey), nsString(aOldValue), nsString(aNewValue),
principalInfo, mIsPrivate));
}
}
DispatchStorageEvent(mDocumentURI, aKey, aOldValue, aNewValue,
@ -204,16 +213,6 @@ LocalStorage::DispatchStorageEvent(const nsAString& aDocumentURI,
{
NotifyChange(aStorage, aPrincipal, aKey, aOldValue, aNewValue,
u"localStorage", aDocumentURI, aIsPrivate, aImmediateDispatch);
// If we are in the parent process and we have the principal, we want to
// broadcast this event to every other process.
if (XRE_IsParentProcess() && aPrincipal) {
for (auto* cp : ContentParent::AllProcesses(ContentParent::eLive)) {
Unused << cp->SendDispatchLocalStorageChange(
nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
nsString(aNewValue), IPC::Principal(aPrincipal), aIsPrivate);
}
}
}
void

Просмотреть файл

@ -24,10 +24,6 @@ namespace dom {
#define DOM_STORAGE_CACHE_KEEP_ALIVE_TIME_MS 20000
// static
StorageDBBridge* LocalStorageCache::sDatabase = nullptr;
bool LocalStorageCache::sDatabaseDown = false;
namespace {
const uint32_t kDefaultSet = 0;
@ -243,13 +239,14 @@ LocalStorageCache::Preload()
return;
}
if (!StartDatabase()) {
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (!storageChild) {
mLoaded = true;
mLoadResult = NS_ERROR_FAILURE;
return;
}
sDatabase->AsyncPreload(this);
storageChild->AsyncPreload(this);
}
namespace {
@ -309,7 +306,7 @@ LocalStorageCache::WaitForPreload(Telemetry::HistogramID aTelemetryID)
// No need to check sDatabase for being non-null since preload is either
// done before we've shut the DB down or when the DB could not start,
// preload has not even be started.
sDatabase->SyncPreload(this);
StorageDBChild::Get()->SyncPreload(this);
}
nsresult
@ -429,17 +426,18 @@ LocalStorageCache::SetItem(const LocalStorage* aStorage, const nsAString& aKey,
data.mKeys.Put(aKey, aValue);
if (aSource == ContentMutation && Persist(aStorage)) {
if (!sDatabase) {
StorageDBChild* storageChild = StorageDBChild::Get();
if (!storageChild) {
NS_ERROR("Writing to localStorage after the database has been shut down"
", data lose!");
return NS_ERROR_NOT_INITIALIZED;
}
if (DOMStringIsNull(aOld)) {
return sDatabase->AsyncAddItem(this, aKey, aValue);
return storageChild->AsyncAddItem(this, aKey, aValue);
}
return sDatabase->AsyncUpdateItem(this, aKey, aValue);
return storageChild->AsyncUpdateItem(this, aKey, aValue);
}
return NS_OK;
@ -470,13 +468,14 @@ LocalStorageCache::RemoveItem(const LocalStorage* aStorage,
data.mKeys.Remove(aKey);
if (aSource == ContentMutation && Persist(aStorage)) {
if (!sDatabase) {
StorageDBChild* storageChild = StorageDBChild::Get();
if (!storageChild) {
NS_ERROR("Writing to localStorage after the database has been shut down"
", data lose!");
return NS_ERROR_NOT_INITIALIZED;
}
return sDatabase->AsyncRemoveItem(this, aKey);
return storageChild->AsyncRemoveItem(this, aKey);
}
return NS_OK;
@ -511,13 +510,14 @@ LocalStorageCache::Clear(const LocalStorage* aStorage,
}
if (aSource == ContentMutation && Persist(aStorage) && (refresh || hadData)) {
if (!sDatabase) {
StorageDBChild* storageChild = StorageDBChild::Get();
if (!storageChild) {
NS_ERROR("Writing to localStorage after the database has been shut down"
", data lose!");
return NS_ERROR_NOT_INITIALIZED;
}
return sDatabase->AsyncClear(this);
return storageChild->AsyncClear(this);
}
return hadData ? NS_OK : NS_SUCCESS_DOM_NO_OPERATION;
@ -672,73 +672,5 @@ StorageUsage::CheckAndSetETLD1UsageDelta(uint32_t aDataSetIndex,
return true;
}
// static
StorageDBBridge*
LocalStorageCache::StartDatabase()
{
if (sDatabase || sDatabaseDown) {
// When sDatabaseDown is at true, sDatabase is null.
// Checking sDatabaseDown flag here prevents reinitialization of
// the database after shutdown.
return sDatabase;
}
if (XRE_IsParentProcess()) {
nsAutoPtr<StorageDBThread> db(new StorageDBThread());
nsresult rv = db->Init();
if (NS_FAILED(rv)) {
return nullptr;
}
sDatabase = db.forget();
} else {
// Use LocalStorageManager::Ensure in case we're called from
// DOMSessionStorageManager's initializer and we haven't yet initialized the
// local storage manager.
RefPtr<StorageDBChild> db = new StorageDBChild(
LocalStorageManager::Ensure());
nsresult rv = db->Init();
if (NS_FAILED(rv)) {
return nullptr;
}
db.forget(&sDatabase);
}
return sDatabase;
}
// static
StorageDBBridge*
LocalStorageCache::GetDatabase()
{
return sDatabase;
}
// static
nsresult
LocalStorageCache::StopDatabase()
{
if (!sDatabase) {
return NS_OK;
}
sDatabaseDown = true;
nsresult rv = sDatabase->Shutdown();
if (XRE_IsParentProcess()) {
delete sDatabase;
} else {
StorageDBChild* child = static_cast<StorageDBChild*>(sDatabase);
NS_RELEASE(child);
}
sDatabase = nullptr;
return rv;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -131,13 +131,6 @@ public:
void GetKeys(const LocalStorage* aStorage, nsTArray<nsString>& aKeys);
// Starts the database engine thread or the IPC bridge
static StorageDBBridge* StartDatabase();
static StorageDBBridge* GetDatabase();
// Stops the thread and flushes all uncommited data
static nsresult StopDatabase();
// LocalStorageCacheBridge
virtual const nsCString Origin() const;
@ -260,13 +253,6 @@ private:
// Whether we have already captured state of the cache preload on our first
// access.
bool mPreloadTelemetryRecorded : 1;
// StorageDBThread on the parent or single process,
// StorageDBChild on the child process.
static StorageDBBridge* sDatabase;
// False until we shut the database down.
static bool sDatabaseDown;
};
// StorageUsage
@ -274,7 +260,7 @@ private:
class StorageUsageBridge
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StorageUsageBridge)
NS_INLINE_DECL_THREADSAFE_VIRTUAL_REFCOUNTING(StorageUsageBridge)
virtual const nsCString& OriginScope() = 0;
virtual void LoadUsage(const int64_t aUsage) = 0;

Просмотреть файл

@ -76,7 +76,7 @@ LocalStorageManager::LocalStorageManager()
// Do this only on the child process. The thread IPC bridge
// is also used to communicate chrome observer notifications.
// Note: must be called after we set sSelf
LocalStorageCache::StartDatabase();
StorageDBChild::GetOrCreate();
}
}
@ -168,9 +168,9 @@ LocalStorageManager::GetOriginUsage(const nsACString& aOriginNoSuffix)
usage = new StorageUsage(aOriginNoSuffix);
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (db) {
db->AsyncGetUsage(usage);
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (storageChild) {
storageChild->AsyncGetUsage(usage);
}
mUsages.Put(aOriginNoSuffix, usage);
@ -234,7 +234,7 @@ LocalStorageManager::GetStorageInternal(CreateMode aCreateMode,
if (aCreateMode == CreateMode::CreateIfShouldPreload) {
// This is a demand to just preload the cache, if the scope has
// no data stored, bypass creation and preload of the cache.
StorageDBBridge* db = LocalStorageCache::GetDatabase();
StorageDBChild* db = StorageDBChild::Get();
if (db) {
if (!db->ShouldPreloadOrigin(LocalStorageManager::CreateOrigin(originAttrSuffix, originKey))) {
return NS_OK;

Просмотреть файл

@ -131,6 +131,7 @@ private:
nsDataHashtable<nsCStringHashKey, RefPtr<StorageUsage> > mUsages;
friend class LocalStorageCache;
friend class StorageDBChild;
// Releases cache since it is no longer referrered by any Storage object.
virtual void DropCache(LocalStorageCache* aCache);

Просмотреть файл

@ -4,7 +4,12 @@
* 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 protocol PContent;
include protocol PBackground;
include "mozilla/dom/quota/SerializationHelpers.h";
using mozilla::OriginAttributesPattern
from "mozilla/OriginAttributes.h";
namespace mozilla {
namespace dom {
@ -12,16 +17,16 @@ namespace dom {
/* This protocol bridges async access to the database thread running on the
* parent process and caches running on the child process.
*/
nested(upto inside_cpow) sync protocol PStorage
sync protocol PBackgroundStorage
{
manager PContent;
manager PBackground;
parent:
async __delete__();
async DeleteMe();
nested(inside_cpow) sync Preload(nsCString originSuffix,
nsCString originNoSuffix,
uint32_t alreadyLoadedCount)
sync Preload(nsCString originSuffix,
nsCString originNoSuffix,
uint32_t alreadyLoadedCount)
returns (nsString[] keys, nsString[] values, nsresult rv);
async AsyncPreload(nsCString originSuffix, nsCString originNoSuffix,
@ -35,8 +40,20 @@ parent:
nsString key);
async AsyncClear(nsCString originSuffix, nsCString originNoSuffix);
async AsyncFlush();
// These are privileged operations for use only by the observer API for
// delayed initialization and clearing origins and will never be used from
// content process children. Ideally these would be guarded by checks or
// exist on a separate, privileged interface, but PBackgroundStorage is
// already insecure.
async Startup();
async ClearAll();
async ClearMatchingOrigin(nsCString originNoSuffix);
async ClearMatchingOriginAttributes(OriginAttributesPattern pattern);
child:
async __delete__();
async Observe(nsCString topic,
nsString originAttributesPattern,
nsCString originScope);

Просмотреть файл

@ -23,6 +23,7 @@
#include "mozIStorageValueArray.h"
#include "mozIStorageFunction.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "nsIObserverService.h"
#include "nsVariant.h"
#include "mozilla/IOInterposer.h"
@ -48,6 +49,11 @@ using namespace StorageUtils;
namespace { // anon
StorageDBThread* sStorageThread = nullptr;
// False until we shut the storage thread down.
bool sStorageThreadDown = false;
// This is only a compatibility code for schema version 0. Returns the 'scope'
// key in the schema version 0 format for the scope column.
nsCString
@ -106,11 +112,64 @@ Scheme0Scope(LocalStorageCacheBridge* aCache)
} // anon
// XXX Fix me!
#if 0
StorageDBBridge::StorageDBBridge()
{
}
#endif
class StorageDBThread::InitHelper final
: public Runnable
{
nsCOMPtr<nsIEventTarget> mOwningThread;
mozilla::Mutex mMutex;
mozilla::CondVar mCondVar;
nsString mProfilePath;
nsresult mMainThreadResultCode;
bool mWaiting;
public:
InitHelper()
: Runnable("dom::StorageDBThread::InitHelper")
, mOwningThread(GetCurrentThreadEventTarget())
, mMutex("InitHelper::mMutex")
, mCondVar(mMutex, "InitHelper::mCondVar")
, mMainThreadResultCode(NS_OK)
, mWaiting(true)
{ }
// Because of the `sync Preload` IPC, we need to be able to synchronously
// initialize, which includes consulting and initializing
// some main-thread-only APIs. Bug 1386441 discusses improving this situation.
nsresult
SyncDispatchAndReturnProfilePath(nsAString& aProfilePath);
private:
~InitHelper() override = default;
nsresult
RunOnMainThread();
NS_DECL_NSIRUNNABLE
};
class StorageDBThread::NoteBackgroundThreadRunnable final
: public Runnable
{
nsCOMPtr<nsIEventTarget> mOwningThread;
public:
NoteBackgroundThreadRunnable()
: Runnable("dom::StorageDBThread::NoteBackgroundThreadRunnable")
, mOwningThread(GetCurrentThreadEventTarget())
{ }
private:
~NoteBackgroundThreadRunnable() override = default;
NS_DECL_NSIRUNNABLE
};
StorageDBThread::StorageDBThread()
: mThread(nullptr)
@ -127,26 +186,104 @@ StorageDBThread::StorageDBThread()
{
}
nsresult
StorageDBThread::Init()
// static
StorageDBThread*
StorageDBThread::Get()
{
nsresult rv;
AssertIsOnBackgroundThread();
return sStorageThread;
}
// static
StorageDBThread*
StorageDBThread::GetOrCreate(const nsString& aProfilePath)
{
AssertIsOnBackgroundThread();
if (sStorageThread || sStorageThreadDown) {
// When sStorageThreadDown is at true, sStorageThread is null.
// Checking sStorageThreadDown flag here prevents reinitialization of
// the storage thread after shutdown.
return sStorageThread;
}
nsAutoPtr<StorageDBThread> storageThread(new StorageDBThread());
nsresult rv = storageThread->Init(aProfilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
sStorageThread = storageThread.forget();
return sStorageThread;
}
// static
nsresult
StorageDBThread::GetProfilePath(nsString& aProfilePath)
{
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
// Need to determine location on the main thread, since
// NS_GetSpecialDirectory access the atom table that can
// be accessed only on the main thread.
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(mDatabaseFile));
NS_ENSURE_SUCCESS(rv, rv);
// NS_GetSpecialDirectory accesses the atom table that can
// only be accessed on the main thread.
nsCOMPtr<nsIFile> profileDir;
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(profileDir));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = profileDir->GetPath(aProfilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// This service has to be started on the main thread currently.
nsCOMPtr<mozIStorageService> ss =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
nsresult
StorageDBThread::Init(const nsString& aProfilePath)
{
AssertIsOnBackgroundThread();
nsresult rv;
nsString profilePath;
if (aProfilePath.IsEmpty()) {
RefPtr<InitHelper> helper = new InitHelper();
rv = helper->SyncDispatchAndReturnProfilePath(profilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
profilePath = aProfilePath;
}
mDatabaseFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mDatabaseFile->InitWithPath(profilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
rv = mDatabaseFile->Append(NS_LITERAL_STRING("webappsstore.sqlite"));
NS_ENSURE_SUCCESS(rv, rv);
// Ensure mozIStorageService init on the main thread first.
nsCOMPtr<mozIStorageService> service =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
// Need to keep the lock to avoid setting mThread later then
// the thread body executes.
MonitorAutoLock monitor(mThreadObserver->GetMonitor());
@ -158,12 +295,20 @@ StorageDBThread::Init()
return NS_ERROR_OUT_OF_MEMORY;
}
RefPtr<NoteBackgroundThreadRunnable> runnable =
new NoteBackgroundThreadRunnable();
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
return NS_OK;
}
nsresult
StorageDBThread::Shutdown()
{
AssertIsOnBackgroundThread();
sStorageThreadDown = true;
if (!mThread) {
return NS_ERROR_NOT_INITIALIZED;
}
@ -904,7 +1049,7 @@ StorageDBThread::DBOperation::Perform(StorageDBThread* aThread)
}
StatementCache* statements;
if (MOZ_UNLIKELY(NS_IsMainThread())) {
if (MOZ_UNLIKELY(IsOnBackgroundThread())) {
statements = &aThread->mReaderStatements;
} else {
statements = &aThread->mWorkerStatements;
@ -1494,5 +1639,84 @@ StorageDBThread::PendingOperations::IsOriginUpdatePending(const nsACString& aOri
return false;
}
nsresult
StorageDBThread::
InitHelper::SyncDispatchAndReturnProfilePath(nsAString& aProfilePath)
{
AssertIsOnBackgroundThread();
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
mozilla::MutexAutoLock autolock(mMutex);
while (mWaiting) {
mCondVar.Wait();
}
if (NS_WARN_IF(NS_FAILED(mMainThreadResultCode))) {
return mMainThreadResultCode;
}
aProfilePath = mProfilePath;
return NS_OK;
}
NS_IMETHODIMP
StorageDBThread::
InitHelper::Run()
{
MOZ_ASSERT(NS_IsMainThread());
nsresult rv = GetProfilePath(mProfilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
mMainThreadResultCode = rv;
}
mozilla::MutexAutoLock lock(mMutex);
MOZ_ASSERT(mWaiting);
mWaiting = false;
mCondVar.Notify();
return NS_OK;
}
NS_IMETHODIMP
StorageDBThread::
NoteBackgroundThreadRunnable::Run()
{
MOZ_ASSERT(NS_IsMainThread());
StorageObserver* observer = StorageObserver::Self();
MOZ_ASSERT(observer);
observer->NoteBackgroundThread(mOwningThread);
return NS_OK;
}
NS_IMETHODIMP
StorageDBThread::
ShutdownRunnable::Run()
{
if (NS_IsMainThread()) {
mDone = true;
return NS_OK;
}
AssertIsOnBackgroundThread();
if (sStorageThread) {
sStorageThread->Shutdown();
delete sStorageThread;
sStorageThread = nullptr;
}
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(this));
return NS_OK;
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -32,6 +32,15 @@ class StorageUsage;
typedef mozilla::storage::StatementCache<mozIStorageStatement> StatementCache;
// XXX Fix me!
// 1. Move comments to StorageDBThread/StorageDBChild.
// 2. Devirtualize relevant methods in StorageDBThread/StorageDBChild.
// 3. Remove relevant methods in StorageDBThread/StorageDBChild that are
// unused.
// 4. Remove this class completely.
//
// See bug 1387636 for more details.
#if 0
// Interface used by the cache to post operations to the asynchronous
// database thread or process.
class StorageDBBridge
@ -100,17 +109,15 @@ public:
// Check whether the scope has any data stored on disk and is thus allowed to
// preload
virtual bool ShouldPreloadOrigin(const nsACString& aOriginNoSuffix) = 0;
// Get the complete list of scopes having data
virtual void GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins) = 0;
};
#endif
// The implementation of the the database engine, this directly works
// with the sqlite or any other db API we are based on
// This class is resposible for collecting and processing asynchronous
// DB operations over caches (LocalStorageCache) communicating though
// LocalStorageCacheBridge interface class
class StorageDBThread final : public StorageDBBridge
class StorageDBThread final
{
public:
class PendingOperations;
@ -287,11 +294,46 @@ public:
Monitor mMonitor;
};
class InitHelper;
class NoteBackgroundThreadRunnable;
class ShutdownRunnable : public Runnable
{
// Only touched on the main thread.
bool& mDone;
public:
explicit ShutdownRunnable(bool& aDone)
: Runnable("dom::StorageDBThread::ShutdownRunnable")
, mDone(aDone)
{
MOZ_ASSERT(NS_IsMainThread());
}
private:
~ShutdownRunnable()
{ }
NS_DECL_NSIRUNNABLE
};
public:
StorageDBThread();
virtual ~StorageDBThread() {}
virtual nsresult Init();
static StorageDBThread*
Get();
static StorageDBThread*
GetOrCreate(const nsString& aProfilePath);
static nsresult
GetProfilePath(nsString& aProfilePath);
virtual nsresult Init(const nsString& aProfilePath);
// Flushes all uncommited data and stops the I/O thread.
virtual nsresult Shutdown();
virtual void AsyncPreload(LocalStorageCacheBridge* aCache,
@ -358,7 +400,9 @@ public:
virtual void AsyncFlush();
virtual bool ShouldPreloadOrigin(const nsACString& aOrigin);
virtual void GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins);
// Get the complete list of scopes having data.
void GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins);
private:
nsCOMPtr<nsIFile> mDatabaseFile;

Просмотреть файл

@ -10,6 +10,10 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PBackgroundParent.h"
#include "mozilla/Unused.h"
#include "nsIDiskSpaceWatcher.h"
#include "nsThreadUtils.h"
@ -17,28 +21,37 @@
namespace mozilla {
namespace dom {
namespace {
StorageDBChild* sStorageChild = nullptr;
// False until we shut the storage child down.
bool sStorageChildDown = false;
}
// ----------------------------------------------------------------------------
// Child
// ----------------------------------------------------------------------------
NS_IMPL_ADDREF(StorageDBChild)
NS_IMETHODIMP_(MozExternalRefCountType) StorageDBChild::Release(void)
class StorageDBChild::ShutdownObserver final
: public nsIObserver
{
NS_PRECONDITION(0 != mRefCnt, "dup release");
nsrefcnt count = --mRefCnt;
NS_LOG_RELEASE(this, count, "StorageDBChild");
if (count == 1 && mIPCOpen) {
Send__delete__(this);
return 0;
public:
ShutdownObserver()
{
MOZ_ASSERT(NS_IsMainThread());
}
if (count == 0) {
mRefCnt = 1;
delete this;
return 0;
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
private:
~ShutdownObserver()
{
MOZ_ASSERT(NS_IsMainThread());
}
return count;
}
};
void
StorageDBChild::AddIPDLReference()
@ -67,6 +80,44 @@ StorageDBChild::~StorageDBChild()
{
}
// static
StorageDBChild*
StorageDBChild::Get()
{
MOZ_ASSERT(NS_IsMainThread());
return sStorageChild;
}
// static
StorageDBChild*
StorageDBChild::GetOrCreate()
{
MOZ_ASSERT(NS_IsMainThread());
if (sStorageChild || sStorageChildDown) {
// When sStorageChildDown is at true, sStorageChild is null.
// Checking sStorageChildDown flag here prevents reinitialization of
// the storage child after shutdown.
return sStorageChild;
}
// Use LocalStorageManager::Ensure in case we're called from
// DOMSessionStorageManager's initializer and we haven't yet initialized the
// local storage manager.
RefPtr<StorageDBChild> storageChild =
new StorageDBChild(LocalStorageManager::Ensure());
nsresult rv = storageChild->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
storageChild.forget(&sStorageChild);
return sStorageChild;
}
nsTHashtable<nsCStringHashKey>&
StorageDBChild::OriginsHavingData()
{
@ -80,9 +131,35 @@ StorageDBChild::OriginsHavingData()
nsresult
StorageDBChild::Init()
{
ContentChild* child = ContentChild::GetSingleton();
MOZ_ASSERT(NS_IsMainThread());
PBackgroundChild* actor = BackgroundChild::GetOrCreateForCurrentThread();
if (NS_WARN_IF(!actor)) {
return NS_ERROR_FAILURE;
}
nsString profilePath;
if (XRE_IsParentProcess()) {
nsresult rv = StorageDBThread::GetProfilePath(profilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
AddIPDLReference();
child->SendPStorageConstructor(this);
actor->SendPBackgroundStorageConstructor(this, profilePath);
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
MOZ_ASSERT(observerService);
nsCOMPtr<nsIObserver> observer = new ShutdownObserver();
MOZ_ALWAYS_SUCCEEDS(
observerService->AddObserver(observer,
"xpcom-shutdown",
false));
return NS_OK;
}
@ -216,6 +293,8 @@ StorageDBChild::RecvObserve(const nsCString& aTopic,
const nsString& aOriginAttributesPattern,
const nsCString& aOriginScope)
{
MOZ_ASSERT(!XRE_IsParentProcess());
StorageObserver::Self()->Notify(
aTopic.get(), aOriginAttributesPattern, aOriginScope);
return IPC_OK();
@ -286,10 +365,87 @@ StorageDBChild::RecvError(const nsresult& aRv)
return IPC_OK();
}
NS_IMPL_ISUPPORTS(StorageDBChild::ShutdownObserver, nsIObserver)
NS_IMETHODIMP
StorageDBChild::
ShutdownObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"));
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (NS_WARN_IF(!observerService)) {
return NS_ERROR_FAILURE;
}
Unused << observerService->RemoveObserver(this, "xpcom-shutdown");
if (sStorageChild) {
sStorageChildDown = true;
MOZ_ALWAYS_TRUE(sStorageChild->PBackgroundStorageChild::SendDeleteMe());
NS_RELEASE(sStorageChild);
sStorageChild = nullptr;
}
return NS_OK;
}
// ----------------------------------------------------------------------------
// Parent
// ----------------------------------------------------------------------------
class StorageDBParent::ObserverSink
: public StorageObserverSink
{
nsCOMPtr<nsIEventTarget> mOwningEventTarget;
// Only touched on the PBackground thread.
StorageDBParent* MOZ_NON_OWNING_REF mActor;
public:
explicit ObserverSink(StorageDBParent* aActor)
: mOwningEventTarget(GetCurrentThreadEventTarget())
, mActor(aActor)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StorageDBParent::ObserverSink);
void
Start();
void
Stop();
private:
~ObserverSink() = default;
void
AddSink();
void
RemoveSink();
void
Notify(const nsCString& aTopic,
const nsString& aOriginAttributesPattern,
const nsCString& aOriginScope);
// StorageObserverSink
nsresult
Observe(const char* aTopic,
const nsAString& aOriginAttrPattern,
const nsACString& aOriginScope) override;
};
NS_IMPL_ADDREF(StorageDBParent)
NS_IMPL_RELEASE(StorageDBParent)
@ -311,78 +467,111 @@ StorageDBParent::ReleaseIPDLReference()
namespace {
class SendInitialChildDataRunnable : public Runnable
class CheckLowDiskSpaceRunnable
: public Runnable
{
nsCOMPtr<nsIEventTarget> mOwningEventTarget;
RefPtr<StorageDBParent> mParent;
bool mLowDiskSpace;
public:
explicit SendInitialChildDataRunnable(StorageDBParent* aParent)
: Runnable("dom::SendInitialChildDataRunnable")
explicit CheckLowDiskSpaceRunnable(StorageDBParent* aParent)
: Runnable("dom::CheckLowDiskSpaceRunnable")
, mOwningEventTarget(GetCurrentThreadEventTarget())
, mParent(aParent)
{}
, mLowDiskSpace(false)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aParent);
}
private:
NS_IMETHOD Run() override
{
if (!mParent->IPCOpen()) {
if (IsOnBackgroundThread()) {
MOZ_ASSERT(mParent);
if (!mParent->IPCOpen()) {
return NS_OK;
}
if (mLowDiskSpace) {
mozilla::Unused << mParent->SendObserve(
nsDependentCString("low-disk-space"), EmptyString(), EmptyCString());
}
mParent = nullptr;
return NS_OK;
}
StorageDBBridge* db = LocalStorageCache::GetDatabase();
if (db) {
InfallibleTArray<nsCString> scopes;
db->GetOriginsHavingData(&scopes);
mozilla::Unused << mParent->SendOriginsHavingData(scopes);
}
MOZ_ASSERT(NS_IsMainThread());
// We need to check if the device is in a low disk space situation, so
// we can forbid in that case any write in localStorage.
nsCOMPtr<nsIDiskSpaceWatcher> diskSpaceWatcher =
do_GetService("@mozilla.org/toolkit/disk-space-watcher;1");
if (!diskSpaceWatcher) {
return NS_OK;
}
bool lowDiskSpace = false;
diskSpaceWatcher->GetIsDiskFull(&lowDiskSpace);
diskSpaceWatcher->GetIsDiskFull(&mLowDiskSpace);
if (lowDiskSpace) {
mozilla::Unused << mParent->SendObserve(
nsDependentCString("low-disk-space"), EmptyString(), EmptyCString());
}
MOZ_ALWAYS_SUCCEEDS(mOwningEventTarget->Dispatch(this, NS_DISPATCH_NORMAL));
return NS_OK;
}
RefPtr<StorageDBParent> mParent;
};
} // namespace
StorageDBParent::StorageDBParent()
: mIPCOpen(false)
StorageDBParent::StorageDBParent(const nsString& aProfilePath)
: mProfilePath(aProfilePath)
, mIPCOpen(false)
{
StorageObserver* observer = StorageObserver::Self();
if (observer) {
observer->AddSink(this);
}
AssertIsOnBackgroundThread();
// We are always open by IPC only
AddIPDLReference();
// Cannot send directly from here since the channel
// is not completely built at this moment.
RefPtr<SendInitialChildDataRunnable> r =
new SendInitialChildDataRunnable(this);
NS_DispatchToCurrentThread(r);
}
StorageDBParent::~StorageDBParent()
{
StorageObserver* observer = StorageObserver::Self();
if (observer) {
observer->RemoveSink(this);
AssertIsOnBackgroundThread();
if (mObserverSink) {
mObserverSink->Stop();
mObserverSink = nullptr;
}
}
void
StorageDBParent::Init()
{
AssertIsOnBackgroundThread();
PBackgroundParent* actor = Manager();
MOZ_ASSERT(actor);
if (BackgroundParent::IsOtherProcessActor(actor)) {
mObserverSink = new ObserverSink(this);
mObserverSink->Start();
}
StorageDBThread* storageThread = StorageDBThread::Get();
if (storageThread) {
InfallibleTArray<nsCString> scopes;
storageThread->GetOriginsHavingData(&scopes);
mozilla::Unused << SendOriginsHavingData(scopes);
}
// We need to check if the device is in a low disk space situation, so
// we can forbid in that case any write in localStorage.
RefPtr<CheckLowDiskSpaceRunnable> runnable =
new CheckLowDiskSpaceRunnable(this);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
}
StorageDBParent::CacheParentBridge*
StorageDBParent::NewCache(const nsACString& aOriginSuffix,
const nsACString& aOriginNoSuffix)
@ -396,32 +585,48 @@ StorageDBParent::ActorDestroy(ActorDestroyReason aWhy)
// Implement me! Bug 1005169
}
mozilla::ipc::IPCResult
StorageDBParent::RecvDeleteMe()
{
AssertIsOnBackgroundThread();
IProtocol* mgr = Manager();
if (!PBackgroundStorageParent::Send__delete__(this)) {
return IPC_FAIL_NO_REASON(mgr);
}
return IPC_OK();
}
mozilla::ipc::IPCResult
StorageDBParent::RecvAsyncPreload(const nsCString& aOriginSuffix,
const nsCString& aOriginNoSuffix,
const bool& aPriority)
{
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
db->AsyncPreload(NewCache(aOriginSuffix, aOriginNoSuffix), aPriority);
storageThread->AsyncPreload(NewCache(aOriginSuffix, aOriginNoSuffix),
aPriority);
return IPC_OK();
}
mozilla::ipc::IPCResult
StorageDBParent::RecvAsyncGetUsage(const nsCString& aOriginNoSuffix)
{
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
// The object releases it self in LoadUsage method
RefPtr<UsageParentBridge> usage =
new UsageParentBridge(this, aOriginNoSuffix);
db->AsyncGetUsage(usage);
storageThread->AsyncGetUsage(usage);
return IPC_OK();
}
@ -512,8 +717,8 @@ StorageDBParent::RecvPreload(const nsCString& aOriginSuffix,
InfallibleTArray<nsString>* aValues,
nsresult* aRv)
{
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
@ -521,7 +726,8 @@ StorageDBParent::RecvPreload(const nsCString& aOriginSuffix,
new SyncLoadCacheHelper(aOriginSuffix, aOriginNoSuffix, aAlreadyLoadedCount,
aKeys, aValues, aRv));
db->SyncPreload(cache, true);
storageThread->SyncPreload(cache, true);
return IPC_OK();
}
@ -531,13 +737,15 @@ StorageDBParent::RecvAsyncAddItem(const nsCString& aOriginSuffix,
const nsString& aKey,
const nsString& aValue)
{
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
nsresult rv = db->AsyncAddItem(NewCache(aOriginSuffix, aOriginNoSuffix), aKey,
aValue);
nsresult rv =
storageThread->AsyncAddItem(NewCache(aOriginSuffix, aOriginNoSuffix),
aKey,
aValue);
if (NS_FAILED(rv) && mIPCOpen) {
mozilla::Unused << SendError(rv);
}
@ -551,13 +759,15 @@ StorageDBParent::RecvAsyncUpdateItem(const nsCString& aOriginSuffix,
const nsString& aKey,
const nsString& aValue)
{
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
nsresult rv = db->AsyncUpdateItem(NewCache(aOriginSuffix, aOriginNoSuffix),
aKey, aValue);
nsresult rv =
storageThread->AsyncUpdateItem(NewCache(aOriginSuffix, aOriginNoSuffix),
aKey,
aValue);
if (NS_FAILED(rv) && mIPCOpen) {
mozilla::Unused << SendError(rv);
}
@ -570,13 +780,14 @@ StorageDBParent::RecvAsyncRemoveItem(const nsCString& aOriginSuffix,
const nsCString& aOriginNoSuffix,
const nsString& aKey)
{
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
nsresult rv = db->AsyncRemoveItem(NewCache(aOriginSuffix, aOriginNoSuffix),
aKey);
nsresult rv =
storageThread->AsyncRemoveItem(NewCache(aOriginSuffix, aOriginNoSuffix),
aKey);
if (NS_FAILED(rv) && mIPCOpen) {
mozilla::Unused << SendError(rv);
}
@ -588,12 +799,13 @@ mozilla::ipc::IPCResult
StorageDBParent::RecvAsyncClear(const nsCString& aOriginSuffix,
const nsCString& aOriginNoSuffix)
{
StorageDBBridge* db = LocalStorageCache::StartDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
nsresult rv = db->AsyncClear(NewCache(aOriginSuffix, aOriginNoSuffix));
nsresult rv =
storageThread->AsyncClear(NewCache(aOriginSuffix, aOriginNoSuffix));
if (NS_FAILED(rv) && mIPCOpen) {
mozilla::Unused << SendError(rv);
}
@ -604,29 +816,76 @@ StorageDBParent::RecvAsyncClear(const nsCString& aOriginSuffix,
mozilla::ipc::IPCResult
StorageDBParent::RecvAsyncFlush()
{
StorageDBBridge* db = LocalStorageCache::GetDatabase();
if (!db) {
StorageDBThread* storageThread = StorageDBThread::Get();
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
db->AsyncFlush();
storageThread->AsyncFlush();
return IPC_OK();
}
// StorageObserverSink
nsresult
StorageDBParent::Observe(const char* aTopic,
const nsAString& aOriginAttributesPattern,
const nsACString& aOriginScope)
mozilla::ipc::IPCResult
StorageDBParent::RecvStartup()
{
if (mIPCOpen) {
mozilla::Unused << SendObserve(nsDependentCString(aTopic),
nsString(aOriginAttributesPattern),
nsCString(aOriginScope));
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
return NS_OK;
return IPC_OK();
}
mozilla::ipc::IPCResult
StorageDBParent::RecvClearAll()
{
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
storageThread->AsyncClearAll();
return IPC_OK();
}
mozilla::ipc::IPCResult
StorageDBParent::RecvClearMatchingOrigin(const nsCString& aOriginNoSuffix)
{
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
storageThread->AsyncClearMatchingOrigin(aOriginNoSuffix);
return IPC_OK();
}
mozilla::ipc::IPCResult
StorageDBParent::RecvClearMatchingOriginAttributes(
const OriginAttributesPattern& aPattern)
{
StorageDBThread* storageThread = StorageDBThread::GetOrCreate(mProfilePath);
if (!storageThread) {
return IPC_FAIL_NO_REASON(this);
}
storageThread->AsyncClearMatchingOriginAttributes(aPattern);
return IPC_OK();
}
void
StorageDBParent::Observe(const nsCString& aTopic,
const nsString& aOriginAttributesPattern,
const nsCString& aOriginScope)
{
if (mIPCOpen) {
mozilla::Unused <<
SendObserve(aTopic, aOriginAttributesPattern, aOriginScope);
}
}
namespace {
@ -692,6 +951,8 @@ private:
break;
}
mParent = nullptr;
return NS_OK;
}
};
@ -719,7 +980,10 @@ StorageDBParent::CacheParentBridge::LoadItem(const nsAString& aKey,
RefPtr<LoadRunnable> r =
new LoadRunnable(mParent, LoadRunnable::loadItem, mOriginSuffix,
mOriginNoSuffix, aKey, aValue);
NS_DispatchToMainThread(r);
MOZ_ALWAYS_SUCCEEDS(
mOwningEventTarget->Dispatch(r, NS_DISPATCH_NORMAL));
return true;
}
@ -736,7 +1000,9 @@ StorageDBParent::CacheParentBridge::LoadDone(nsresult aRv)
RefPtr<LoadRunnable> r =
new LoadRunnable(mParent, LoadRunnable::loadDone, mOriginSuffix,
mOriginNoSuffix, aRv);
NS_DispatchToMainThread(r);
MOZ_ALWAYS_SUCCEEDS(
mOwningEventTarget->Dispatch(r, NS_DISPATCH_NORMAL));
}
void
@ -746,6 +1012,42 @@ StorageDBParent::CacheParentBridge::LoadWait()
MOZ_ASSERT(false);
}
// XXX Fix me!
// This should be just:
// NS_IMPL_RELEASE_WITH_DESTROY(StorageDBParent::CacheParentBridge, Destroy)
// But due to different strings used for refcount logging and different return
// types, this is done manually for now.
NS_IMETHODIMP_(void)
StorageDBParent::CacheParentBridge::Release(void)
{
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
nsrefcnt count = --mRefCnt;
NS_LOG_RELEASE(this, count, "LocalStorageCacheBridge");
if (0 == count) {
mRefCnt = 1; /* stabilize */
/* enable this to find non-threadsafe destructors: */
/* NS_ASSERT_OWNINGTHREAD(_class); */
Destroy();
}
}
void
StorageDBParent::CacheParentBridge::Destroy()
{
if (mOwningEventTarget->IsOnCurrentThread()) {
delete this;
return;
}
RefPtr<Runnable> destroyRunnable =
NewNonOwningRunnableMethod("CacheParentBridge::Destroy",
this,
&CacheParentBridge::Destroy);
MOZ_ALWAYS_SUCCEEDS(mOwningEventTarget->Dispatch(destroyRunnable,
NS_DISPATCH_NORMAL));
}
// StorageDBParent::UsageParentBridge
namespace {
@ -770,6 +1072,9 @@ private:
}
mozilla::Unused << mParent->SendLoadUsage(mOriginScope, mUsage);
mParent = nullptr;
return NS_OK;
}
@ -784,7 +1089,168 @@ void
StorageDBParent::UsageParentBridge::LoadUsage(const int64_t aUsage)
{
RefPtr<UsageRunnable> r = new UsageRunnable(mParent, mOriginScope, aUsage);
NS_DispatchToMainThread(r);
MOZ_ALWAYS_SUCCEEDS(mOwningEventTarget->Dispatch(r, NS_DISPATCH_NORMAL));
}
// XXX Fix me!
// This should be just:
// NS_IMPL_RELEASE_WITH_DESTROY(StorageDBParent::UsageParentBridge, Destroy)
// But due to different strings used for refcount logging, this is done manually
// for now.
NS_IMETHODIMP_(MozExternalRefCountType)
StorageDBParent::UsageParentBridge::Release(void)
{
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
nsrefcnt count = --mRefCnt;
NS_LOG_RELEASE(this, count, "StorageUsageBridge");
if (count == 0) {
Destroy();
return 0;
}
return count;
}
void
StorageDBParent::UsageParentBridge::Destroy()
{
if (mOwningEventTarget->IsOnCurrentThread()) {
delete this;
return;
}
RefPtr<Runnable> destroyRunnable =
NewNonOwningRunnableMethod("UsageParentBridge::Destroy",
this,
&UsageParentBridge::Destroy);
MOZ_ALWAYS_SUCCEEDS(mOwningEventTarget->Dispatch(destroyRunnable,
NS_DISPATCH_NORMAL));
}
void
StorageDBParent::
ObserverSink::Start()
{
AssertIsOnBackgroundThread();
RefPtr<Runnable> runnable =
NewRunnableMethod("StorageDBParent::ObserverSink::AddSink",
this,
&StorageDBParent::ObserverSink::AddSink);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
}
void
StorageDBParent::
ObserverSink::Stop()
{
AssertIsOnBackgroundThread();
mActor = nullptr;
RefPtr<Runnable> runnable =
NewRunnableMethod("StorageDBParent::ObserverSink::RemoveSink",
this,
&StorageDBParent::ObserverSink::RemoveSink);
MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(runnable));
}
void
StorageDBParent::
ObserverSink::AddSink()
{
MOZ_ASSERT(NS_IsMainThread());
StorageObserver* observer = StorageObserver::Self();
if (observer) {
observer->AddSink(this);
}
}
void
StorageDBParent::
ObserverSink::RemoveSink()
{
MOZ_ASSERT(NS_IsMainThread());
StorageObserver* observer = StorageObserver::Self();
if (observer) {
observer->RemoveSink(this);
}
}
void
StorageDBParent::
ObserverSink::Notify(const nsCString& aTopic,
const nsString& aOriginAttributesPattern,
const nsCString& aOriginScope)
{
AssertIsOnBackgroundThread();
if (mActor) {
mActor->Observe(aTopic, aOriginAttributesPattern, aOriginScope);
}
}
nsresult
StorageDBParent::
ObserverSink::Observe(const char* aTopic,
const nsAString& aOriginAttributesPattern,
const nsACString& aOriginScope)
{
MOZ_ASSERT(NS_IsMainThread());
RefPtr<Runnable> runnable =
NewRunnableMethod<nsCString, nsString, nsCString>(
"StorageDBParent::ObserverSink::Observe2",
this,
&StorageDBParent::ObserverSink::Notify,
aTopic,
aOriginAttributesPattern,
aOriginScope);
MOZ_ALWAYS_SUCCEEDS(
mOwningEventTarget->Dispatch(runnable, NS_DISPATCH_NORMAL));
return NS_OK;
}
/*******************************************************************************
* Exported functions
******************************************************************************/
PBackgroundStorageParent*
AllocPBackgroundStorageParent(const nsString& aProfilePath)
{
AssertIsOnBackgroundThread();
return new StorageDBParent(aProfilePath);
}
mozilla::ipc::IPCResult
RecvPBackgroundStorageConstructor(PBackgroundStorageParent* aActor,
const nsString& aProfilePath)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
auto* actor = static_cast<StorageDBParent*>(aActor);
actor->Init();
return IPC_OK();
}
bool
DeallocPBackgroundStorageParent(PBackgroundStorageParent* aActor)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
StorageDBParent* actor = static_cast<StorageDBParent*>(aActor);
actor->ReleaseIPDLReference();
return true;
}
} // namespace dom

Просмотреть файл

@ -7,8 +7,8 @@
#ifndef mozilla_dom_StorageIPC_h
#define mozilla_dom_StorageIPC_h
#include "mozilla/dom/PStorageChild.h"
#include "mozilla/dom/PStorageParent.h"
#include "mozilla/dom/PBackgroundStorageChild.h"
#include "mozilla/dom/PBackgroundStorageParent.h"
#include "StorageDBThread.h"
#include "LocalStorageCache.h"
#include "StorageObserver.h"
@ -22,21 +22,29 @@ class OriginAttributesPattern;
namespace dom {
class LocalStorageManager;
class PBackgroundStorageParent;
// Child side of the IPC protocol, exposes as DB interface but
// is responsible to send all requests to the parent process
// and expects asynchronous answers. Those are then transparently
// forwarded back to consumers on the child process.
class StorageDBChild final : public StorageDBBridge
, public PStorageChild
class StorageDBChild final
: public PBackgroundStorageChild
{
class ShutdownObserver;
virtual ~StorageDBChild();
public:
explicit StorageDBChild(LocalStorageManager* aManager);
NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
NS_IMETHOD_(MozExternalRefCountType) Release(void);
static StorageDBChild*
Get();
static StorageDBChild*
GetOrCreate();
NS_INLINE_DECL_REFCOUNTING(StorageDBChild);
void AddIPDLReference();
void ReleaseIPDLReference();
@ -68,17 +76,21 @@ public:
}
virtual void AsyncClearMatchingOrigin(const nsACString& aOriginNoSuffix)
{ /* NO-OP on the child process */ }
{
MOZ_CRASH("Shouldn't be called!");
}
virtual void AsyncClearMatchingOriginAttributes(const OriginAttributesPattern& aPattern)
{ /* NO-OP on the child process */ }
{
MOZ_CRASH("Shouldn't be called!");
}
virtual void AsyncFlush()
{ SendAsyncFlush(); }
{
MOZ_CRASH("Shouldn't be called!");
}
virtual bool ShouldPreloadOrigin(const nsACString& aOriginNoSuffix);
virtual void GetOriginsHavingData(InfallibleTArray<nsCString>* aOrigins)
{ NS_NOTREACHED("Not implemented for child process"); }
private:
mozilla::ipc::IPCResult RecvObserve(const nsCString& aTopic,
@ -98,9 +110,6 @@ private:
nsTHashtable<nsCStringHashKey>& OriginsHavingData();
ThreadSafeAutoRefCnt mRefCnt;
NS_DECL_OWNINGTHREAD
// Held to get caches to forward answers to.
RefPtr<LocalStorageManager> mManager;
@ -123,13 +132,17 @@ private:
// LocalStorageCache consumer.
// Also responsible for forwardning all chrome operation notifications
// such as cookie cleaning etc to the child process.
class StorageDBParent final : public PStorageParent
, public StorageObserverSink
class StorageDBParent final : public PBackgroundStorageParent
{
class ObserverSink;
virtual ~StorageDBParent();
public:
StorageDBParent();
explicit StorageDBParent(const nsString& aProfilePath);
void
Init();
NS_IMETHOD_(MozExternalRefCountType) AddRef(void);
NS_IMETHOD_(MozExternalRefCountType) Release(void);
@ -147,7 +160,8 @@ public:
CacheParentBridge(StorageDBParent* aParentDB,
const nsACString& aOriginSuffix,
const nsACString& aOriginNoSuffix)
: mParent(aParentDB)
: mOwningEventTarget(GetCurrentThreadSerialEventTarget())
, mParent(aParentDB)
, mOriginSuffix(aOriginSuffix), mOriginNoSuffix(aOriginNoSuffix)
, mLoaded(false), mLoadedCount(0) {}
virtual ~CacheParentBridge() {}
@ -167,7 +181,14 @@ public:
virtual void LoadDone(nsresult aRv);
virtual void LoadWait();
NS_IMETHOD_(void)
Release(void);
private:
void
Destroy();
nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
RefPtr<StorageDBParent> mParent;
nsCString mOriginSuffix, mOriginNoSuffix;
bool mLoaded;
@ -180,14 +201,23 @@ public:
public:
UsageParentBridge(StorageDBParent* aParentDB,
const nsACString& aOriginScope)
: mParent(aParentDB), mOriginScope(aOriginScope) {}
: mOwningEventTarget(GetCurrentThreadSerialEventTarget())
, mParent(aParentDB)
, mOriginScope(aOriginScope) {}
virtual ~UsageParentBridge() {}
// StorageUsageBridge
virtual const nsCString& OriginScope() { return mOriginScope; }
virtual void LoadUsage(const int64_t usage);
NS_IMETHOD_(MozExternalRefCountType)
Release(void);
private:
void
Destroy();
nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
RefPtr<StorageDBParent> mParent;
nsCString mOriginScope;
};
@ -195,6 +225,8 @@ public:
private:
// IPC
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvDeleteMe() override;
mozilla::ipc::IPCResult RecvAsyncPreload(const nsCString& aOriginSuffix,
const nsCString& aOriginNoSuffix,
const bool& aPriority) override;
@ -220,15 +252,30 @@ private:
const nsCString& aOriginNoSuffix) override;
mozilla::ipc::IPCResult RecvAsyncFlush() override;
// StorageObserverSink
virtual nsresult Observe(const char* aTopic,
const nsAString& aOriginAttrPattern,
const nsACString& aOriginScope) override;
mozilla::ipc::IPCResult RecvStartup() override;
mozilla::ipc::IPCResult RecvClearAll() override;
mozilla::ipc::IPCResult RecvClearMatchingOrigin(
const nsCString& aOriginNoSuffix) override;
mozilla::ipc::IPCResult RecvClearMatchingOriginAttributes(
const OriginAttributesPattern& aPattern) override;
void Observe(const nsCString& aTopic,
const nsString& aOriginAttrPattern,
const nsCString& aOriginScope);
private:
CacheParentBridge* NewCache(const nsACString& aOriginSuffix,
const nsACString& aOriginNoSuffix);
RefPtr<ObserverSink> mObserverSink;
// A hack to deal with deadlock between the parent process main thread and
// background thread when invoking StorageDBThread::GetOrCreate because it
// cannot safely perform a synchronous dispatch back to the main thread
// (because we are already synchronously doing things on the stack).
// Populated for the same process actors, empty for other process actors.
nsString mProfilePath;
ThreadSafeAutoRefCnt mRefCnt;
NS_DECL_OWNINGTHREAD
@ -236,6 +283,16 @@ private:
bool mIPCOpen;
};
PBackgroundStorageParent*
AllocPBackgroundStorageParent(const nsString& aProfilePath);
mozilla::ipc::IPCResult
RecvPBackgroundStorageConstructor(PBackgroundStorageParent* aActor,
const nsString& aProfilePath);
bool
DeallocPBackgroundStorageParent(PBackgroundStorageParent* aActor);
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -70,8 +70,9 @@ StorageObserver::Init()
// Shutdown
obs->AddObserver(sSelf, "profile-after-change", true);
obs->AddObserver(sSelf, "profile-before-change", true);
obs->AddObserver(sSelf, "xpcom-shutdown", true);
if (XRE_IsParentProcess()) {
obs->AddObserver(sSelf, "profile-before-change", true);
}
// Observe low device storage notifications.
obs->AddObserver(sSelf, "disk-space-watcher", true);
@ -145,6 +146,12 @@ StorageObserver::Notify(const char* aTopic,
}
}
void
StorageObserver::NoteBackgroundThread(nsIEventTarget* aBackgroundThread)
{
mBackgroundThread = aBackgroundThread;
}
NS_IMETHODIMP
StorageObserver::Observe(nsISupports* aSubject,
const char* aTopic,
@ -154,6 +161,8 @@ StorageObserver::Observe(nsISupports* aSubject,
// Start the thread that opens the database.
if (!strcmp(aTopic, kStartupTopic)) {
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->RemoveObserver(this, kStartupTopic);
@ -169,6 +178,8 @@ StorageObserver::Observe(nsISupports* aSubject,
// Timer callback used to start the database a short timer after startup
if (!strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC)) {
MOZ_ASSERT(XRE_IsParentProcess());
nsCOMPtr<nsITimer> timer = do_QueryInterface(aSubject);
if (!timer) {
return NS_ERROR_UNEXPECTED;
@ -177,8 +188,12 @@ StorageObserver::Observe(nsISupports* aSubject,
if (timer == mDBThreadStartDelayTimer) {
mDBThreadStartDelayTimer = nullptr;
StorageDBBridge* db = LocalStorageCache::StartDatabase();
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (NS_WARN_IF(!storageChild)) {
return NS_ERROR_FAILURE;
}
storageChild->SendStartup();
}
return NS_OK;
@ -190,10 +205,16 @@ StorageObserver::Observe(nsISupports* aSubject,
return NS_OK;
}
StorageDBBridge* db = LocalStorageCache::StartDatabase();
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (NS_WARN_IF(!storageChild)) {
return NS_ERROR_FAILURE;
}
db->AsyncClearAll();
storageChild->AsyncClearAll();
if (XRE_IsParentProcess()) {
storageChild->SendClearAll();
}
Notify("cookie-cleared");
@ -254,10 +275,16 @@ StorageObserver::Observe(nsISupports* aSubject,
}
if (!strcmp(aTopic, "extension:purge-localStorage")) {
StorageDBBridge* db = LocalStorageCache::StartDatabase();
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (NS_WARN_IF(!storageChild)) {
return NS_ERROR_FAILURE;
}
db->AsyncClearAll();
storageChild->AsyncClearAll();
if (XRE_IsParentProcess()) {
storageChild->SendClearAll();
}
Notify("extension:purge-localStorage-caches");
@ -287,10 +314,14 @@ StorageObserver::Observe(nsISupports* aSubject,
rv = CreateReversedDomain(aceDomain, originScope);
NS_ENSURE_SUCCESS(rv, rv);
StorageDBBridge* db = LocalStorageCache::StartDatabase();
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
if (XRE_IsParentProcess()) {
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (NS_WARN_IF(!storageChild)) {
return NS_ERROR_FAILURE;
}
db->AsyncClearMatchingOrigin(originScope);
storageChild->SendClearMatchingOrigin(originScope);
}
Notify("domain-data-cleared", EmptyString(), originScope);
@ -306,16 +337,20 @@ StorageObserver::Observe(nsISupports* aSubject,
// Clear data of the origins whose prefixes will match the suffix.
if (!strcmp(aTopic, "clear-origin-attributes-data")) {
MOZ_ASSERT(XRE_IsParentProcess());
OriginAttributesPattern pattern;
if (!pattern.Init(nsDependentString(aData))) {
NS_ERROR("Cannot parse origin attributes pattern");
return NS_ERROR_FAILURE;
}
StorageDBBridge* db = LocalStorageCache::StartDatabase();
NS_ENSURE_TRUE(db, NS_ERROR_FAILURE);
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (NS_WARN_IF(!storageChild)) {
return NS_ERROR_FAILURE;
}
db->AsyncClearMatchingOriginAttributes(pattern);
storageChild->SendClearMatchingOriginAttributes(pattern);
Notify("origin-attr-pattern-cleared", nsDependentString(aData));
@ -328,11 +363,20 @@ StorageObserver::Observe(nsISupports* aSubject,
return NS_OK;
}
if (!strcmp(aTopic, "profile-before-change") ||
!strcmp(aTopic, "xpcom-shutdown")) {
rv = LocalStorageCache::StopDatabase();
if (NS_FAILED(rv)) {
NS_WARNING("Error while stopping Storage DB background thread");
if (!strcmp(aTopic, "profile-before-change")) {
MOZ_ASSERT(XRE_IsParentProcess());
if (mBackgroundThread) {
bool done = false;
RefPtr<StorageDBThread::ShutdownRunnable> shutdownRunnable =
new StorageDBThread::ShutdownRunnable(done);
MOZ_ALWAYS_SUCCEEDS(
mBackgroundThread->Dispatch(shutdownRunnable, NS_DISPATCH_NORMAL));
MOZ_ALWAYS_TRUE(SpinEventLoopUntil([&]() { return done; }));
mBackgroundThread = nullptr;
}
return NS_OK;
@ -350,11 +394,13 @@ StorageObserver::Observe(nsISupports* aSubject,
#ifdef DOM_STORAGE_TESTS
if (!strcmp(aTopic, "domstorage-test-flush-force")) {
StorageDBBridge* db = LocalStorageCache::GetDatabase();
if (db) {
db->AsyncFlush();
StorageDBChild* storageChild = StorageDBChild::GetOrCreate();
if (NS_WARN_IF(!storageChild)) {
return NS_ERROR_FAILURE;
}
storageChild->SendAsyncFlush();
return NS_OK;
}

Просмотреть файл

@ -51,6 +51,9 @@ public:
const nsAString& aOriginAttributesPattern = EmptyString(),
const nsACString& aOriginScope = EmptyCString());
void
NoteBackgroundThread(nsIEventTarget* aBackgroundThread);
private:
virtual ~StorageObserver() {}
@ -58,6 +61,8 @@ private:
static StorageObserver* sSelf;
nsCOMPtr<nsIEventTarget> mBackgroundThread;
// Weak references
nsTArray<StorageObserverSink*> mSinks;
nsCOMPtr<nsITimer> mDBThreadStartDelayTimer;

Просмотреть файл

@ -34,7 +34,7 @@ UNIFIED_SOURCES += [
]
IPDL_SOURCES += [
'PStorage.ipdl',
'PBackgroundStorage.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')

Просмотреть файл

@ -155,12 +155,12 @@ async function verifyTabPreload(knownTab, expectStorageExists) {
* Instruct the given tab to execute the given series of mutations. For
* simplicity, the mutations representation matches the expected events rep.
*/
async function mutateTabStorage(knownTab, mutations) {
async function mutateTabStorage(knownTab, mutations, sentinelValue) {
await ContentTask.spawn(
knownTab.tab.linkedBrowser,
{ mutations },
{ mutations, sentinelValue },
function(args) {
return content.wrappedJSObject.mutateStorage(args.mutations);
return content.wrappedJSObject.mutateStorage(args);
});
}
@ -169,25 +169,33 @@ async function mutateTabStorage(knownTab, mutations) {
* received events. verifyTabStorageEvents is the corresponding method to
* check and assert the recorded events.
*/
async function recordTabStorageEvents(knownTab) {
async function recordTabStorageEvents(knownTab, sentinelValue) {
await ContentTask.spawn(
knownTab.tab.linkedBrowser,
{},
function() {
return content.wrappedJSObject.listenForStorageEvents();
sentinelValue,
function(sentinelValue) {
return content.wrappedJSObject.listenForStorageEvents(sentinelValue);
});
}
/**
* Retrieve the current localStorage contents perceived by the tab and assert
* that they match the provided expected state.
*
* If maybeSentinel is non-null, it's assumed to be a string that identifies the
* value we should be waiting for the sentinel key to take on. This is
* necessary because we cannot make any assumptions about when state will be
* propagated to the given process. See the comments in
* page_localstorage_e10s.js for more context. In general, a sentinel value is
* required for correctness unless the process in question is the one where the
* writes were performed or verifyTabStorageEvents was used.
*/
async function verifyTabStorageState(knownTab, expectedState) {
async function verifyTabStorageState(knownTab, expectedState, maybeSentinel) {
let actualState = await ContentTask.spawn(
knownTab.tab.linkedBrowser,
{},
function() {
return content.wrappedJSObject.getStorageState();
maybeSentinel,
function(maybeSentinel) {
return content.wrappedJSObject.getStorageState(maybeSentinel);
});
for (let [expectedKey, expectedValue] of Object.entries(expectedState)) {
@ -205,6 +213,9 @@ async function verifyTabStorageState(knownTab, expectedState) {
* Retrieve and clear the storage events recorded by the tab and assert that
* they match the provided expected events. For simplicity, the expected events
* representation is the same as that used by mutateTabStorage.
*
* Note that by convention for test readability we are passed a 3rd argument of
* the sentinel value, but we don't actually care what it is.
*/
async function verifyTabStorageEvents(knownTab, expectedEvents) {
let actualEvents = await ContentTask.spawn(
@ -318,9 +329,12 @@ add_task(async function() {
await verifyTabPreload(readerTab, false);
// - Configure the tabs.
await recordTabStorageEvents(listenerTab);
const initialSentinel = 'initial';
const noSentinelCheck = null;
await recordTabStorageEvents(listenerTab, initialSentinel);
// - Issue the initial batch of writes and verify.
info("initial writes");
const initialWriteMutations = [
//[key (null=clear), newValue (null=delete), oldValue (verification)]
["getsCleared", "1", null],
@ -341,14 +355,40 @@ add_task(async function() {
alsoStays: "6"
};
await mutateTabStorage(writerTab, initialWriteMutations);
await mutateTabStorage(writerTab, initialWriteMutations, initialSentinel);
await verifyTabStorageState(writerTab, initialWriteState);
await verifyTabStorageEvents(listenerTab, initialWriteMutations);
await verifyTabStorageState(listenerTab, initialWriteState);
await verifyTabStorageState(readerTab, initialWriteState);
// We expect the writer tab to have the correct state because it just did the
// writes. We do not perform a sentinel-check because the writes should be
// locally available and consistent.
await verifyTabStorageState(writerTab, initialWriteState, noSentinelCheck);
// We expect the listener tab to have heard all events despite preload not
// having occurred and despite not issuing any reads or writes itself. We
// intentionally check the events before the state because we're most
// interested in adding the listener having had a side-effect of subscribing
// to changes for the process.
//
// We ensure it had a chance to hear all of the events because we told
// recordTabStorageEvents to listen for the given sentinel. The state check
// then does not need to do a sentinel check.
await verifyTabStorageEvents(
listenerTab, initialWriteMutations, initialSentinel);
await verifyTabStorageState(
listenerTab, initialWriteState, noSentinelCheck);
// We expect the reader tab to retrieve the current localStorage state from
// the database. Because of the above checks, we are confident that the
// writes have hit PBackground and therefore that the (synchronous) state
// retrieval contains all the data we need. No sentinel-check is required.
await verifyTabStorageState(readerTab, initialWriteState, noSentinelCheck);
// - Issue second set of writes from lateWriteThenListen
// This tests that our new tab that begins by issuing only writes is building
// on top of the existing state (although we don't verify that until after the
// next set of mutations). We also verify that the initial "writerTab" that
// was our first tab and started with only writes sees the writes, even though
// it did not add an event listener.
info("late writes");
const lateWriteSentinel = 'lateWrite';
const lateWriteMutations = [
["lateStays", "10", null],
["lateClobbered", "latePre", null],
@ -361,15 +401,24 @@ add_task(async function() {
lateClobbered: "lastPost"
});
await mutateTabStorage(lateWriteThenListenTab, lateWriteMutations);
await recordTabStorageEvents(lateWriteThenListenTab);
await recordTabStorageEvents(listenerTab, lateWriteSentinel);
await verifyTabStorageState(writerTab, lateWriteState);
await verifyTabStorageEvents(listenerTab, lateWriteMutations);
await verifyTabStorageState(listenerTab, lateWriteState);
await verifyTabStorageState(readerTab, lateWriteState);
await mutateTabStorage(
lateWriteThenListenTab, lateWriteMutations, lateWriteSentinel);
// Verify the writer tab saw the writes. It has to wait for the sentinel to
// appear before checking.
await verifyTabStorageState(writerTab, lateWriteState, lateWriteSentinel);
// Wait for the sentinel event before checking the events and then the state.
await verifyTabStorageEvents(
listenerTab, lateWriteMutations, lateWriteSentinel);
await verifyTabStorageState(listenerTab, lateWriteState, noSentinelCheck);
// We need to wait for the sentinel to show up for the reader.
await verifyTabStorageState(readerTab, lateWriteState, lateWriteSentinel);
// - Issue last set of writes from writerTab.
info("last set of writes");
const lastWriteSentinel = 'lastWrite';
const lastWriteMutations = [
["lastStays", "20", null],
["lastDeleted", "21", null],
@ -382,14 +431,24 @@ add_task(async function() {
lastClobbered: "lastPost"
});
await mutateTabStorage(writerTab, lastWriteMutations);
await recordTabStorageEvents(listenerTab, lastWriteSentinel);
await recordTabStorageEvents(lateWriteThenListenTab, lastWriteSentinel);
await verifyTabStorageState(writerTab, lastWriteState);
await verifyTabStorageEvents(listenerTab, lastWriteMutations);
await verifyTabStorageState(listenerTab, lastWriteState);
await verifyTabStorageState(readerTab, lastWriteState);
await verifyTabStorageEvents(lateWriteThenListenTab, lastWriteMutations);
await verifyTabStorageState(lateWriteThenListenTab, lastWriteState);
await mutateTabStorage(writerTab, lastWriteMutations, lastWriteSentinel);
// The writer performed the writes, no need to wait for the sentinel.
await verifyTabStorageState(writerTab, lastWriteState, noSentinelCheck);
// Wait for the sentinel event to be received, then check.
await verifyTabStorageEvents(
listenerTab, lastWriteMutations, lastWriteSentinel);
await verifyTabStorageState(listenerTab, lastWriteState, noSentinelCheck);
// We need to wait for the sentinel to show up for the reader.
await verifyTabStorageState(readerTab, lastWriteState, lastWriteSentinel);
// Wait for the sentinel event to be received, then check.
await verifyTabStorageEvents(
lateWriteThenListenTab, lastWriteMutations, lastWriteSentinel);
await verifyTabStorageState(
lateWriteThenListenTab, lastWriteState, noSentinelCheck);
// - Force a LocalStorage DB flush so mOriginsHavingData is updated.
// mOriginsHavingData is only updated when the storage thread runs its
@ -397,9 +456,11 @@ add_task(async function() {
// that a flush has occurred before moving on to the next step,
// mOriginsHavingData may not include our origin when it's sent down to the
// child process.
info("flush to make preload check work");
await triggerAndWaitForLocalStorageFlush();
// - Open a fresh tab and make sure it sees the precache/preload
info("late open preload check");
const lateOpenSeesPreload =
await openTestTabInOwnProcess("lateOpenSeesPreload", knownTabs);
await verifyTabPreload(lateOpenSeesPreload, true);

Просмотреть файл

@ -5,23 +5,78 @@
<script>
/**
* Helper page used by browser_localStorage_e10s.js.
*
* We expose methods to be invoked by ContentTask.spawn() calls.
* ContentTask.spawn() uses the message manager and is PContent-based. When
* LocalStorage was PContent-managed, ordering was inherently ensured so we
* could assume each page had already received all relevant events. Now some
* explicit type of coordination is required.
*
* This gets complicated because:
* - LocalStorage is an ugly API that gives us almost unlimited implementation
* flexibility in the face of multiple processes. It's also an API that sites
* may misuse which may encourage us to leverage that flexibility in the
* future to improve performance at the expense of propagation latency, and
* possibly involving content-observable coalescing of events.
* - The Quantum DOM effort and its event labeling and separate task queues and
* green threading and current LocalStorage implementation mean that using
* other PBackground-based APIs such as BroadcastChannel may not provide
* reliable ordering guarantees. Specifically, it's hard to guarantee that
* a BroadcastChannel postMessage() issued after a series of LocalStorage
* writes won't be received by the target window before the writes are
* perceived. At least not without constraining the implementations of both
* APIs.
* - Some of our tests explicitly want to verify LocalStorage behavior without
* having a "storage" listener, so we can't add a storage listener if the test
* didn't already want one.
*
* We use 2 approaches for coordination:
* 1. If we're already listening for events, we listen for the sentinel value to
* be written. This is efficient and appropriate in this case.
* 2. If we're not listening for events, we use setTimeout(0) to poll the
* localStorage key and value until it changes to our expected value.
* setTimeout(0) eventually clamps to setTimeout(4), so in the event we are
* experiencing delays, we have reasonable, non-CPU-consuming back-off in
* place that leaves the CPU free to time out and fail our test if something
* broke. This is ugly but makes us less brittle.
*
* Both of these involve mutateStorage writing the sentinel value at the end of
* the batch. All of our result-returning methods accordingly filter out the
* sentinel key/value pair.
**/
var pageName = document.location.search.substring(1);
window.addEventListener(
"load",
() => { document.getElementById("pageNameH").textContent = pageName; });
var recordedEvents = null;
function storageListener(event) {
recordedEvents.push([event.key, event.newValue, event.oldValue]);
// Key that conveys the end of a write batch. Filtered out from state and
// events.
const SENTINEL_KEY = 'WRITE_BATCH_SENTINEL';
var storageEventsPromise = null;
function listenForStorageEvents(sentinelValue) {
const recordedEvents = [];
storageEventsPromise = new Promise(function(resolve, reject) {
window.addEventListener(
"storage",
function thisHandler(event) {
if (event.key === SENTINEL_KEY) {
// There should be no way for this to have the wrong value, but reject
// if it is wrong.
if (event.newValue === sentinelValue) {
window.removeEventListener("storage", thisHandler);
resolve(recordedEvents);
} else {
reject(event.newValue);
}
} else {
recordedEvents.push([event.key, event.newValue, event.oldValue]);
}
});
});
}
function listenForStorageEvents() {
recordedEvents = [];
window.addEventListener("storage", storageListener);
}
function mutateStorage(mutations) {
function mutateStorage({ mutations, sentinelValue }) {
mutations.forEach(function([key, value]) {
if (key !== null) {
if (value === null) {
@ -33,22 +88,48 @@ function mutateStorage(mutations) {
localStorage.clear();
}
});
localStorage.setItem(SENTINEL_KEY, sentinelValue);
}
function getStorageState() {
// Returns a promise that is resolve when the sentinel key has taken on the
// sentinel value. Oddly structured to make sure promises don't let us
// accidentally side-step the timeout clamping logic.
function waitForSentinelValue(sentinelValue) {
return new Promise(function(resolve) {
function checkFunc() {
if (localStorage.getItem(SENTINEL_KEY) === sentinelValue) {
resolve();
} else {
// I believe linters will only yell at us if we use a non-zero constant.
// Other forms of back-off were considered, including attempting to
// issue a round-trip through PBackground, but that still potentially
// runs afoul of labeling while also making us dependent on unrelated
// APIs.
setTimeout(checkFunc, 0);
}
}
checkFunc();
});
}
async function getStorageState(maybeSentinel) {
if (maybeSentinel) {
await waitForSentinelValue(maybeSentinel);
}
let numKeys = localStorage.length;
let state = {};
for (var iKey = 0; iKey < numKeys; iKey++) {
let key = localStorage.key(iKey);
state[key] = localStorage.getItem(key);
if (key !== SENTINEL_KEY) {
state[key] = localStorage.getItem(key);
}
}
return state;
}
function returnAndClearStorageEvents() {
let loggedEvents = recordedEvents;
recordedEvents = [];
return loggedEvents;
return storageEventsPromise;
}
</script>
</head>

Просмотреть файл

@ -317,12 +317,6 @@ partial interface Window {
attribute EventHandler onuserproximity;
attribute EventHandler ondevicelight;
#ifdef MOZ_B2G
attribute EventHandler onmoztimechange;
attribute EventHandler onmoznetworkupload;
attribute EventHandler onmoznetworkdownload;
#endif
void dump(DOMString str);
/**

Просмотреть файл

@ -1131,14 +1131,6 @@ if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']:
'External.webidl',
]
if CONFIG['MOZ_B2G']:
WEBIDL_FILES += [
'MozApplicationEvent.webidl'
]
GENERATED_EVENTS_WEBIDL_FILES += [
'MozApplicationEvent.webidl'
]
if CONFIG['ACCESSIBILITY']:
WEBIDL_FILES += [
'AccessibleNode.webidl',

Просмотреть файл

@ -1802,18 +1802,6 @@ nsPermissionManager::AddInternal(nsIPrincipal* aPrincipal,
id = aID;
}
#ifdef MOZ_B2G
// When we do the initial addition of the permissions we don't want to
// inherit session specific permissions from other tabs or apps
// so we ignore them and set the permission to PROMPT_ACTION if it was
// previously allowed or denied by the user.
if (aIgnoreSessionPermissions &&
aExpireType == nsIPermissionManager::EXPIRE_SESSION) {
aPermission = nsIPermissionManager::PROMPT_ACTION;
aExpireType = nsIPermissionManager::EXPIRE_NEVER;
}
#endif // MOZ_B2G
entry->GetPermissions().AppendElement(PermissionEntry(id, typeIndex, aPermission,
aExpireType, aExpireTime,
aModificationTime));

Просмотреть файл

@ -885,7 +885,7 @@ class DrawTargetCapture;
* may be used either through a Snapshot or by flushing the target and directly
* accessing the backing store a DrawTarget was created with.
*/
class DrawTarget : public RefCounted<DrawTarget>
class DrawTarget : public external::AtomicRefCounted<DrawTarget>
{
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTarget)

Просмотреть файл

@ -35,9 +35,6 @@ namespace gl {
StaticMutex GLLibraryEGL::sMutex;
GLLibraryEGL sEGLLibrary;
#ifdef MOZ_B2G
MOZ_THREAD_LOCAL(EGLContext) GLLibraryEGL::sCurrentContext;
#endif
// should match the order of EGLExtensions, and be null-terminated.
static const char* sEGLExtensionNames[] = {
@ -320,11 +317,6 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId
mozilla::ScopedGfxFeatureReporter reporter("EGL");
#ifdef MOZ_B2G
if (!sCurrentContext.init())
MOZ_CRASH("GFX: Tls init failed");
#endif
#ifdef XP_WIN
if (!mEGLLibrary) {
// On Windows, the GLESv2, EGL and DXSDK libraries are shipped with libxul and

Просмотреть файл

@ -486,32 +486,12 @@ private:
} mSymbols;
public:
#ifdef MOZ_B2G
EGLContext CachedCurrentContext() {
return sCurrentContext.get();
}
void UnsetCachedCurrentContext() {
sCurrentContext.set(nullptr);
}
void SetCachedCurrentContext(EGLContext aCtx) {
sCurrentContext.set(aCtx);
}
bool CachedCurrentContextMatches() {
return sCurrentContext.get() == fGetCurrentContext();
}
private:
static MOZ_THREAD_LOCAL(EGLContext) sCurrentContext;
public:
#else
EGLContext CachedCurrentContext() {
return nullptr;
}
void UnsetCachedCurrentContext() {}
void SetCachedCurrentContext(EGLContext aCtx) { }
bool CachedCurrentContextMatches() { return true; }
#endif
private:
bool mInitialized;

Просмотреть файл

@ -35,6 +35,7 @@ var touch_action_prefs = basic_pan_prefs.slice(); // make a copy
touch_action_prefs.push(["layout.css.touch_action.enabled", true]);
var isWindows = (getPlatform() == "windows");
touch_action_prefs.push(["apz.test.fails_with_native_injection", isWindows]);
var subtests = [
// Simple tests to exercise basic panning behaviour

Просмотреть файл

@ -1075,7 +1075,8 @@ TextureClient::CreateForDrawing(TextureForwarder* aAllocator,
TextureData* data = nullptr;
#ifdef XP_WIN
if (aLayersBackend == LayersBackend::LAYERS_D3D11 &&
if ((aLayersBackend == LayersBackend::LAYERS_D3D11 ||
aLayersBackend == LayersBackend::LAYERS_WR) &&
(moz2DBackend == gfx::BackendType::DIRECT2D ||
moz2DBackend == gfx::BackendType::DIRECT2D1_1 ||
(!!(aAllocFlags & ALLOC_FOR_OUT_OF_BAND_CONTENT) &&

Просмотреть файл

@ -327,6 +327,9 @@ DXGITextureData::PrepareDrawTargetInLock(OpenMode aMode)
}
}
// Reset transform
mDrawTarget->SetTransform(Matrix());
if (mNeedsClear) {
mDrawTarget->ClearRect(Rect(0, 0, mSize.width, mSize.height));
mNeedsClear = false;

Просмотреть файл

@ -673,6 +673,14 @@ WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback
bool sync = mTarget != nullptr;
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
// Skip the synchronization for buffer since we also skip the painting during
// device-reset status.
if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
if (WrBridge()->GetSyncObject() &&
WrBridge()->GetSyncObject()->IsSyncObjectValid()) {
WrBridge()->GetSyncObject()->Synchronize();
}
}
{
AutoProfilerTracing
tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");

Просмотреть файл

@ -57,6 +57,7 @@
#include <d3d10_1.h>
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/gfxVars.h"
#include "nsMemory.h"
@ -478,6 +479,10 @@ gfxWindowsPlatform::GetContentBackendFor(mozilla::layers::LayersBackend aLayers)
return defaultBackend;
}
if (aLayers == LayersBackend::LAYERS_WR && gfx::gfxVars::UseWebRenderANGLE()) {
return defaultBackend;
}
if (defaultBackend == BackendType::DIRECT2D1_1) {
// We can't have D2D without D3D11 layers, so fallback to Skia.
return BackendType::SKIA;

Просмотреть файл

@ -33,11 +33,11 @@ interface nsIStringBundle : nsISupports
[noscript, binaryname(GetStringFromName)]
AString GetStringFromNameCpp(in string aName);
// this is kind of like smprintf - except that you can
// this is kind of like ssprintf - except that you can
// only pass it unicode strings, using the %S formatting character.
// the id or name should refer to a string in the bundle that
// uses %S.. do NOT try to use any other types.
// this uses nsTextFormatter::smprintf to do the dirty work.
// this uses nsTextFormatter::ssprintf to do the dirty work.
AString formatStringFromID(in long aID,
[array, size_is(length)] in wstring params,
in unsigned long length);

Просмотреть файл

@ -25,9 +25,11 @@
#include "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
#include "mozilla/dom/ipc/PendingIPCBlobChild.h"
#include "mozilla/dom/quota/PQuotaChild.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/dom/GamepadEventChannelChild.h"
#include "mozilla/dom/GamepadTestChannelChild.h"
#include "mozilla/dom/MessagePortChild.h"
#include "mozilla/dom/LocalStorage.h"
#include "mozilla/ipc/IPCStreamAlloc.h"
#include "mozilla/ipc/PBackgroundTestChild.h"
#include "mozilla/ipc/PChildToParentStreamChild.h"
@ -77,6 +79,8 @@ using mozilla::dom::asmjscache::PAsmJSCacheEntryChild;
using mozilla::dom::cache::PCacheChild;
using mozilla::dom::cache::PCacheStorageChild;
using mozilla::dom::cache::PCacheStreamControlChild;
using mozilla::dom::LocalStorage;
using mozilla::dom::StorageDBChild;
using mozilla::dom::WebAuthnTransactionChild;
@ -202,6 +206,23 @@ BackgroundChildImpl::DeallocPBackgroundIndexedDBUtilsChild(
return true;
}
BackgroundChildImpl::PBackgroundStorageChild*
BackgroundChildImpl::AllocPBackgroundStorageChild(const nsString& aProfilePath)
{
MOZ_CRASH("PBackgroundStorageChild actors should be manually constructed!");
}
bool
BackgroundChildImpl::DeallocPBackgroundStorageChild(
PBackgroundStorageChild* aActor)
{
MOZ_ASSERT(aActor);
StorageDBChild* child = static_cast<StorageDBChild*>(aActor);
child->ReleaseIPDLReference();
return true;
}
PPendingIPCBlobChild*
BackgroundChildImpl::AllocPPendingIPCBlobChild(const IPCBlob& aBlob)
{
@ -578,6 +599,32 @@ BackgroundChildImpl::DeallocPHttpBackgroundChannelChild(PHttpBackgroundChannelCh
return true;
}
mozilla::ipc::IPCResult
BackgroundChildImpl::RecvDispatchLocalStorageChange(
const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate)
{
if (!NS_IsMainThread()) {
return IPC_OK();
}
nsresult rv;
nsCOMPtr<nsIPrincipal> principal =
PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
if (NS_WARN_IF(NS_FAILED(rv))) {
return IPC_FAIL_NO_REASON(this);
}
LocalStorage::DispatchStorageEvent(aDocumentURI, aKey, aOldValue, aNewValue,
principal, aIsPrivate, nullptr, true);
return IPC_OK();
}
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -70,6 +70,12 @@ protected:
DeallocPBackgroundIndexedDBUtilsChild(PBackgroundIndexedDBUtilsChild* aActor)
override;
virtual PBackgroundStorageChild*
AllocPBackgroundStorageChild(const nsString& aProfilePath) override;
virtual bool
DeallocPBackgroundStorageChild(PBackgroundStorageChild* aActor) override;
virtual PPendingIPCBlobChild*
AllocPPendingIPCBlobChild(const IPCBlob& aBlob) override;
@ -208,6 +214,14 @@ protected:
virtual bool
DeallocPHttpBackgroundChannelChild(PHttpBackgroundChannelChild* aActor) override;
virtual mozilla::ipc::IPCResult
RecvDispatchLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate) override;
};
class BackgroundChildImpl::ThreadLocal final

Просмотреть файл

@ -214,6 +214,11 @@ private:
static uint64_t
GetChildID(PBackgroundParent* aBackgroundActor);
// Forwarded from BackgroundParent.
static bool
GetLiveActorArray(PBackgroundParent* aBackgroundActor,
nsTArray<PBackgroundParent*>& aLiveActorArray);
// Forwarded from BackgroundParent.
static bool
Alloc(ContentParent* aContent,
@ -703,6 +708,15 @@ BackgroundParent::GetChildID(PBackgroundParent* aBackgroundActor)
return ParentImpl::GetChildID(aBackgroundActor);
}
// static
bool
BackgroundParent::GetLiveActorArray(
PBackgroundParent* aBackgroundActor,
nsTArray<PBackgroundParent*>& aLiveActorArray)
{
return ParentImpl::GetLiveActorArray(aBackgroundActor, aLiveActorArray);
}
// static
bool
BackgroundParent::Alloc(ContentParent* aContent,
@ -871,6 +885,33 @@ ParentImpl::GetChildID(PBackgroundParent* aBackgroundActor)
return 0;
}
// static
bool
ParentImpl::GetLiveActorArray(PBackgroundParent* aBackgroundActor,
nsTArray<PBackgroundParent*>& aLiveActorArray)
{
AssertIsOnBackgroundThread();
MOZ_ASSERT(aBackgroundActor);
MOZ_ASSERT(aLiveActorArray.IsEmpty());
auto actor = static_cast<ParentImpl*>(aBackgroundActor);
if (actor->mActorDestroyed) {
MOZ_ASSERT(false,
"GetLiveActorArray called after ActorDestroy was called!");
return false;
}
if (!actor->mLiveActorArray) {
return true;
}
for (ParentImpl* liveActor : *actor->mLiveActorArray) {
aLiveActorArray.AppendElement(liveActor);
}
return true;
}
// static
bool
ParentImpl::Alloc(ContentParent* aContent,

Просмотреть файл

@ -67,6 +67,10 @@ public:
static uint64_t
GetChildID(PBackgroundParent* aBackgroundActor);
static bool
GetLiveActorArray(PBackgroundParent* aBackgroundActor,
nsTArray<PBackgroundParent*>& aLiveActorArray);
private:
// Only called by ContentParent for cross-process actors.
static bool

Просмотреть файл

@ -29,6 +29,7 @@
#include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
#include "mozilla/dom/ipc/PendingIPCBlobParent.h"
#include "mozilla/dom/quota/ActorsParent.h"
#include "mozilla/dom/StorageIPC.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/IPCStreamAlloc.h"
@ -242,6 +243,64 @@ BackgroundParentImpl::RecvFlushPendingFileDeletions()
return IPC_OK();
}
auto
BackgroundParentImpl::AllocPBackgroundStorageParent(const nsString& aProfilePath)
-> PBackgroundStorageParent*
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
return mozilla::dom::AllocPBackgroundStorageParent(aProfilePath);
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvPBackgroundStorageConstructor(
PBackgroundStorageParent* aActor,
const nsString& aProfilePath)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
return mozilla::dom::RecvPBackgroundStorageConstructor(aActor, aProfilePath);
}
bool
BackgroundParentImpl::DeallocPBackgroundStorageParent(
PBackgroundStorageParent* aActor)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
return mozilla::dom::DeallocPBackgroundStorageParent(aActor);
}
mozilla::ipc::IPCResult
BackgroundParentImpl::RecvBroadcastLocalStorageChange(
const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate)
{
nsTArray<PBackgroundParent*> liveActorArray;
if (NS_WARN_IF(!BackgroundParent::GetLiveActorArray(this, liveActorArray))) {
return IPC_FAIL_NO_REASON(this);
}
for (auto* liveActor : liveActorArray) {
if (liveActor != this) {
Unused << liveActor->SendDispatchLocalStorageChange(
nsString(aDocumentURI), nsString(aKey), nsString(aOldValue),
nsString(aNewValue), aPrincipalInfo, aIsPrivate);
}
}
return IPC_OK();
}
PPendingIPCBlobParent*
BackgroundParentImpl::AllocPPendingIPCBlobParent(const IPCBlob& aBlob)
{

Просмотреть файл

@ -63,6 +63,24 @@ protected:
virtual mozilla::ipc::IPCResult
RecvFlushPendingFileDeletions() override;
virtual PBackgroundStorageParent*
AllocPBackgroundStorageParent(const nsString& aProfilePath) override;
virtual mozilla::ipc::IPCResult
RecvPBackgroundStorageConstructor(PBackgroundStorageParent* aActor,
const nsString& aProfilePath) override;
virtual bool
DeallocPBackgroundStorageParent(PBackgroundStorageParent* aActor) override;
virtual mozilla::ipc::IPCResult
RecvBroadcastLocalStorageChange(const nsString& aDocumentURI,
const nsString& aKey,
const nsString& aOldValue,
const nsString& aNewValue,
const PrincipalInfo& aPrincipalInfo,
const bool& aIsPrivate) override;
virtual PPendingIPCBlobParent*
AllocPPendingIPCBlobParent(const IPCBlob& aBlob) override;

Просмотреть файл

@ -979,6 +979,42 @@ struct ParamTraits<mozilla::Variant<Ts...>>
}
};
template<typename T>
struct ParamTraits<mozilla::dom::Optional<T>>
{
typedef mozilla::dom::Optional<T> paramType;
static void Write(Message* aMsg, const paramType& aParam)
{
if (aParam.WasPassed()) {
WriteParam(aMsg, true);
WriteParam(aMsg, aParam.Value());
return;
}
WriteParam(aMsg, false);
}
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
{
bool wasPassed = false;
if (!ReadParam(aMsg, aIter, &wasPassed)) {
return false;
}
aResult->Reset();
if (wasPassed) {
if (!ReadParam(aMsg, aIter, &aResult->Construct())) {
return false;
}
}
return true;
}
};
} /* namespace IPC */
#endif /* __IPC_GLUE_IPCMESSAGEUTILS_H__ */

Просмотреть файл

@ -33,13 +33,8 @@ using mozilla::Move;
// Undo the damage done by mozzconf.h
#undef compress
// Logging seems to be somewhat broken on b2g.
#ifdef MOZ_B2G
#define IPC_LOG(...)
#else
static mozilla::LazyLogModule sLogModule("ipc");
#define IPC_LOG(...) MOZ_LOG(sLogModule, LogLevel::Debug, (__VA_ARGS__))
#endif
/*
* IPC design:

Просмотреть файл

@ -5,6 +5,7 @@
include protocol PAsmJSCacheEntry;
include protocol PBackgroundIDBFactory;
include protocol PBackgroundIndexedDBUtils;
include protocol PBackgroundStorage;
include protocol PBackgroundTest;
include protocol PBroadcastChannel;
include protocol PCache;
@ -53,6 +54,7 @@ sync protocol PBackground
manages PAsmJSCacheEntry;
manages PBackgroundIDBFactory;
manages PBackgroundIndexedDBUtils;
manages PBackgroundStorage;
manages PBackgroundTest;
manages PBroadcastChannel;
manages PCache;
@ -86,6 +88,15 @@ parent:
// Use only for testing!
async FlushPendingFileDeletions();
async PBackgroundStorage(nsString profilePath);
async BroadcastLocalStorageChange(nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue,
PrincipalInfo principalInfo,
bool isPrivate);
async PVsync();
async PCameras();
@ -129,6 +140,13 @@ child:
async PPendingIPCBlob(IPCBlob blob);
async DispatchLocalStorageChange(nsString documentURI,
nsString key,
nsString oldValue,
nsString newValue,
PrincipalInfo principalInfo,
bool isPrivate);
both:
// PIPCBlobInputStream is created on the parent side only if the child starts
// a migration.

Просмотреть файл

@ -189,6 +189,7 @@ LOCAL_INCLUDES += [
'/caps',
'/dom/broadcastchannel',
'/dom/indexedDB',
'/dom/storage',
'/dom/workers',
'/media/webrtc/trunk',
'/xpcom/build',

Просмотреть файл

@ -930,7 +930,7 @@ description =
description =
[PBrowserStream::NPN_RequestRead]
description =
[PStorage::Preload]
[PBackgroundStorage::Preload]
description =
[PRemoteSpellcheckEngine::Check]
description =

Просмотреть файл

@ -197,18 +197,19 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
// values
NS_NAMED_LITERAL_STRING(kPageAndTotal, "&PT");
if (aStr.Find(kPageAndTotal) != kNotFound) {
char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumAndTotalsFormat.get(), mPageNum, mTotNumPages);
aNewStr.ReplaceSubstring(kPageAndTotal, nsDependentString(uStr));
free(uStr);
nsAutoString uStr;
nsTextFormatter::ssprintf(uStr, mPD->mPageNumAndTotalsFormat.get(),
mPageNum, mTotNumPages);
aNewStr.ReplaceSubstring(kPageAndTotal, uStr);
}
// Search to see if the page number code is in the string
// and replace the page number code with the actual value
NS_NAMED_LITERAL_STRING(kPage, "&P");
if (aStr.Find(kPage) != kNotFound) {
char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat.get(), mPageNum);
aNewStr.ReplaceSubstring(kPage, nsDependentString(uStr));
free(uStr);
nsAutoString uStr;
nsTextFormatter::ssprintf(uStr, mPD->mPageNumFormat.get(), mPageNum);
aNewStr.ReplaceSubstring(kPage, uStr);
}
NS_NAMED_LITERAL_STRING(kTitle, "&T");
@ -223,9 +224,9 @@ nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
NS_NAMED_LITERAL_STRING(kPageTotal, "&L");
if (aStr.Find(kPageTotal) != kNotFound) {
char16_t * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat.get(), mTotNumPages);
aNewStr.ReplaceSubstring(kPageTotal, nsDependentString(uStr));
free(uStr);
nsAutoString uStr;
nsTextFormatter::ssprintf(uStr, mPD->mPageNumFormat.get(), mTotNumPages);
aNewStr.ReplaceSubstring(kPageTotal, uStr);
}
}

Просмотреть файл

@ -1892,7 +1892,8 @@ nsDisplayList::GetBounds(nsDisplayListBuilder* aBuilder) const {
nsRect
nsDisplayList::GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
const ActiveScrolledRoot* aASR) const {
const ActiveScrolledRoot* aASR,
nsRect* aVisibleRect) const {
nsRect bounds;
for (nsDisplayItem* i = GetBottom(); i != nullptr; i = i->GetAbove()) {
nsRect r = i->GetClippedBounds(aBuilder);
@ -1908,6 +1909,9 @@ nsDisplayList::GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
r = clip->GetClipRect();
}
}
if (aVisibleRect) {
aVisibleRect->UnionRect(*aVisibleRect, i->GetVisibleRect());
}
bounds.UnionRect(bounds, r);
}
return bounds;

Просмотреть файл

@ -2517,9 +2517,14 @@ public:
* If there is an item in this list which is not bounded with respect to
* aASR (i.e. which does not have "finite bounds" with respect to aASR),
* then this method trigger an assertion failure.
* The optional aVisibleRect out argument can be set to non-null if the
* caller is also interested to know the visible rect. This can be used
* to get the visible rect efficiently without traversing the display list
* twice.
*/
nsRect GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
const ActiveScrolledRoot* aASR) const;
const ActiveScrolledRoot* aASR,
nsRect* aVisibleRect = nullptr) const;
/**
* Find the topmost display item that returns a non-null frame, and return
@ -3822,7 +3827,9 @@ public:
*/
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
{
mBounds = mList.GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot);
nsRect visibleRect;
mBounds = mList.GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot,
&visibleRect);
// The display list may contain content that's visible outside the visible
// rect (i.e. the current dirty rect) passed in when the item was created.
// This happens when the dirty rect has been restricted to the visual
@ -3830,7 +3837,7 @@ public:
// rects in nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay), but that
// frame contains placeholders for out-of-flows that aren't descendants of
// the frame.
mVisibleRect.UnionRect(mBaseVisibleRect, mList.GetVisibleRect());
mVisibleRect.UnionRect(mBaseVisibleRect, visibleRect);
}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;

Просмотреть файл

@ -649,9 +649,7 @@ Preferences::IsServiceAvailable()
bool
Preferences::InitStaticMembers()
{
#ifndef MOZ_B2G
MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
#endif
if (!sShutdown && !sPreferences) {
MOZ_ASSERT(NS_IsMainThread());

Просмотреть файл

@ -1426,7 +1426,7 @@ pref("javascript.options.wasm", true);
pref("javascript.options.wasm_baselinejit", false);
pref("javascript.options.native_regexp", true);
pref("javascript.options.parallel_parsing", true);
#if !defined(RELEASE_OR_BETA) && !defined(ANDROID) && !defined(MOZ_B2G) && !defined(XP_IOS)
#if !defined(RELEASE_OR_BETA) && !defined(ANDROID) && !defined(XP_IOS)
pref("javascript.options.asyncstack", true);
#else
pref("javascript.options.asyncstack", false);
@ -2495,14 +2495,6 @@ pref("font.name-list.monospace.x-math", "monospace");
// These fonts are ignored the underline offset, instead of it, the underline is lowered to bottom of its em descent.
pref("font.blacklist.underline_offset", "FangSong,Gulim,GulimChe,MingLiU,MingLiU-ExtB,MingLiU_HKSCS,MingLiU-HKSCS-ExtB,MS Gothic,MS Mincho,MS PGothic,MS PMincho,MS UI Gothic,PMingLiU,PMingLiU-ExtB,SimHei,SimSun,SimSun-ExtB,Hei,Kai,Apple LiGothic,Apple LiSung,Osaka");
#ifdef MOZ_B2G
// Whitelist of fonts that ship with B2G that do not include space lookups in
// default features. This allows us to skip analyzing the GSUB/GPOS tables
// unless features are explicitly enabled.
// Use NSPR_LOG_MODULES=fontinit:5 to dump out details of space lookups
pref("font.whitelist.skip_default_features_space_check", "Fira Sans,Fira Mono");
#endif
pref("images.dither", "auto");
pref("security.directory", "");
@ -4415,7 +4407,7 @@ pref("gfx.font_rendering.fontconfig.max_generic_substitutions", 3);
#endif
#endif
#if defined(ANDROID) || defined(MOZ_B2G)
#if defined(ANDROID)
pref("font.size.fixed.ar", 12);
@ -4433,65 +4425,10 @@ pref("font.size.fixed.x-unicode", 12);
pref("font.default.x-western", "sans-serif");
pref("font.size.fixed.x-western", 12);
# ANDROID || MOZ_B2G
# ANDROID
#endif
#if defined(MOZ_B2G)
// Gonk, FxOS Simulator, B2G Desktop and Mulet.
// TODO: some entries could probably be cleaned up.
// ar
pref("font.name-list.serif.el", "Droid Serif"); // not Charis SIL Compact, only has a few Greek chars
pref("font.name-list.sans-serif.el", "Fira Sans");
pref("font.name-list.monospace.el", "Fira Mono");
pref("font.name-list.serif.he", "Charis SIL Compact");
pref("font.name-list.sans-serif.he", "Fira Sans, Droid Sans Hebrew");
pref("font.name-list.monospace.he", "Fira Mono");
pref("font.name-list.serif.ja", "Charis SIL Compact");
pref("font.name-list.sans-serif.ja", "Fira Sans, MotoyaLMaru, MotoyaLCedar, Droid Sans Japanese");
pref("font.name-list.monospace.ja", "MotoyaLMaru, MotoyaLCedar, Fira Mono");
pref("font.name-list.serif.ko", "Charis SIL Compact");
pref("font.name-list.sans-serif.ko", "Fira Sans");
pref("font.name-list.monospace.ko", "Fira Mono");
pref("font.name-list.serif.th", "Charis SIL Compact");
pref("font.name-list.sans-serif.th", "Fira Sans, Noto Sans Thai, Droid Sans Thai");
pref("font.name-list.monospace.th", "Fira Mono");
pref("font.name-list.serif.x-cyrillic", "Charis SIL Compact");
pref("font.name-list.sans-serif.x-cyrillic", "Fira Sans");
pref("font.name-list.monospace.x-cyrillic", "Fira Mono");
pref("font.name-list.serif.x-unicode", "Charis SIL Compact");
pref("font.name-list.sans-serif.x-unicode", "Fira Sans");
pref("font.name-list.monospace.x-unicode", "Fira Mono");
pref("font.name-list.serif.x-western", "Charis SIL Compact");
pref("font.name-list.sans-serif.x-western", "Fira Sans");
pref("font.name-list.monospace.x-western", "Fira Mono");
pref("font.name-list.serif.zh-CN", "Charis SIL Compact");
pref("font.name-list.sans-serif.zh-CN", "Fira Sans, Droid Sans Fallback");
pref("font.name-list.monospace.zh-CN", "Fira Mono");
pref("font.name-list.serif.zh-HK", "Charis SIL Compact");
pref("font.name-list.sans-serif.zh-HK", "Fira Sans, Droid Sans Fallback");
pref("font.name-list.monospace.zh-HK", "Fira Mono");
pref("font.name-list.serif.zh-TW", "Charis SIL Compact");
pref("font.name-list.sans-serif.zh-TW", "Fira Sans, Droid Sans Fallback");
pref("font.name-list.monospace.zh-TW", "Fira Mono");
pref("font.name-list.serif.x-math", "Latin Modern Math, STIX Two Math, XITS Math, Cambria Math, Libertinus Math, DejaVu Math TeX Gyre, TeX Gyre Bonum Math, TeX Gyre Pagella Math, TeX Gyre Schola, TeX Gyre Termes Math, STIX Math, Asana Math, STIXGeneral, DejaVu Serif, DejaVu Sans, Charis SIL Compact");
pref("font.name-list.sans-serif.x-math", "Fira Sans");
pref("font.name-list.monospace.x-math", "Fira Mono");
#elif defined(ANDROID)
#if defined(ANDROID)
// We use the bundled fonts for Firefox for Android
pref("font.name-list.serif.ar", "Noto Naskh Arabic, Noto Serif, Droid Serif");

Просмотреть файл

@ -526,9 +526,7 @@ nsresult PREF_GetBoolPref(const char *pref_name, bool * return_value, bool get_d
nsresult
PREF_DeleteBranch(const char *branch_name)
{
#ifndef MOZ_B2G
MOZ_ASSERT(NS_IsMainThread());
#endif
int len = (int)strlen(branch_name);
@ -589,9 +587,7 @@ PREF_ClearUserPref(const char *pref_name)
nsresult
PREF_ClearAllUserPrefs()
{
#ifndef MOZ_B2G
MOZ_ASSERT(NS_IsMainThread());
#endif
if (!gHashTable)
return NS_ERROR_NOT_INITIALIZED;
@ -735,9 +731,7 @@ inInitArray(const char* key)
PrefHashEntry* pref_HashTableLookup(const char *key)
{
#ifndef MOZ_B2G
MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
#endif
MOZ_ASSERT((!XRE_IsContentProcess() || gPhase != START),
"pref access before commandline prefs set");
/* If you're hitting this assertion, you've added a pref access to start up.
@ -756,9 +750,7 @@ PrefHashEntry* pref_HashTableLookup(const char *key)
nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, uint32_t flags)
{
#ifndef MOZ_B2G
MOZ_ASSERT(NS_IsMainThread());
#endif
if (!gHashTable)
return NS_ERROR_OUT_OF_MEMORY;

Просмотреть файл

@ -229,10 +229,7 @@ public:
}
double operator/(const BaseTimeDuration& aOther) const
{
#ifndef MOZ_B2G
// Bug 1066388 - This fails on B2G ICS Emulator
MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
#endif
return ValueCalculator::DivideDouble(mValue, aOther.mValue);
}
BaseTimeDuration operator%(const BaseTimeDuration& aOther) const

Просмотреть файл

@ -27,7 +27,7 @@
// The tickler only applies to wifi on mobile right now. Hopefully it
// can also be restricted to particular handset models in the future.
#if defined(ANDROID) && !defined(MOZ_B2G)
#if defined(ANDROID)
#define MOZ_USE_WIFI_TICKLER
#endif

Просмотреть файл

@ -9,8 +9,10 @@
// http://wiki.mozilla.org/Gecko:Effective_TLD_Service
#include "mozilla/ArrayUtils.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/MemoryReporting.h"
#include "MainThreadUtils.h"
#include "nsEffectiveTLDService.h"
#include "nsIIDNService.h"
#include "nsNetUtil.h"
@ -19,6 +21,13 @@
#include "nsNetCID.h"
#include "nsServiceManagerUtils.h"
namespace etld_dafsa {
// Generated file that includes kDafsa
#include "etld_data.inc"
} // namespace etld_dafsa
using namespace mozilla;
NS_IMPL_ISUPPORTS(nsEffectiveTLDService, nsIEffectiveTLDService,
@ -26,56 +35,11 @@ NS_IMPL_ISUPPORTS(nsEffectiveTLDService, nsIEffectiveTLDService,
// ----------------------------------------------------------------------
#define ETLD_STR_NUM_1(line) str##line
#define ETLD_STR_NUM(line) ETLD_STR_NUM_1(line)
#define ETLD_ENTRY_OFFSET(name) offsetof(struct etld_string_list, ETLD_STR_NUM(__LINE__))
const ETLDEntry ETLDEntry::entries[] = {
#define ETLD_ENTRY(name, ex, wild) { ETLD_ENTRY_OFFSET(name), ex, wild },
#include "etld_data.inc"
#undef ETLD_ENTRY
};
const union ETLDEntry::etld_strings ETLDEntry::strings = {
{
#define ETLD_ENTRY(name, ex, wild) name,
#include "etld_data.inc"
#undef ETLD_ENTRY
}
};
/* static */ const ETLDEntry*
ETLDEntry::GetEntry(const char* aDomain)
{
size_t i;
if (BinarySearchIf(entries, 0, ArrayLength(ETLDEntry::entries),
Cmp(aDomain), &i)) {
return &entries[i];
}
return nullptr;
}
// Dummy function to statically ensure that our indices don't overflow
// the storage provided for them.
void
ETLDEntry::FuncForStaticAsserts(void)
{
#define ETLD_ENTRY(name, ex, wild) \
static_assert(ETLD_ENTRY_OFFSET(name) < (1 << ETLD_ENTRY_N_INDEX_BITS), \
"invalid strtab index");
#include "etld_data.inc"
#undef ETLD_ENTRY
}
#undef ETLD_ENTRY_OFFSET
#undef ETLD_STR_NUM
#undef ETLD_STR_NUM1
// ----------------------------------------------------------------------
static nsEffectiveTLDService *gService = nullptr;
nsEffectiveTLDService::nsEffectiveTLDService()
: mIDNService()
, mGraph(etld_dafsa::kDafsa)
{
}
@ -86,24 +50,6 @@ nsEffectiveTLDService::Init()
mIDNService = do_GetService(NS_IDNSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
#ifdef DEBUG
// Sanity-check the eTLD entries.
for (uint32_t i = 0; i < ArrayLength(ETLDEntry::entries); i++) {
const char* domain = ETLDEntry::entries[i].GetEffectiveTLDName();
nsDependentCString name(domain);
nsAutoCString normalizedName(domain);
MOZ_ASSERT(NS_SUCCEEDED(NormalizeHostname(normalizedName)),
"normalization failure!");
MOZ_ASSERT(name.Equals(normalizedName), "domain not normalized!");
// Domains must be in sorted order for binary search to work.
if (i > 0) {
const char* domain0 = ETLDEntry::entries[i - 1].GetEffectiveTLDName();
MOZ_ASSERT(strcmp(domain0, domain) < 0, "domains not in sorted order!");
}
}
#endif
MOZ_ASSERT(!gService);
gService = this;
RegisterWeakMemoryReporter(this);
@ -244,6 +190,9 @@ nsEffectiveTLDService::GetBaseDomainInternal(nsCString &aHostname,
int32_t aAdditionalParts,
nsACString &aBaseDomain)
{
const int kExceptionRule = 1;
const int kWildcardRule = 2;
if (aHostname.IsEmpty())
return NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS;
@ -263,6 +212,20 @@ nsEffectiveTLDService::GetBaseDomainInternal(nsCString &aHostname,
if (result == PR_SUCCESS)
return NS_ERROR_HOST_IS_IP_ADDRESS;
// Lookup in the cache if this is a normal query.
TLDCacheEntry* entry = nullptr;
if (aAdditionalParts == 1) {
if (LookupForAdd(aHostname, &entry)) {
// There was a match, just return the cached value.
aBaseDomain = entry->mBaseDomain;
if (trailingDot) {
aBaseDomain.Append('.');
}
return NS_OK;
}
}
// Walk up the domain tree, most specific to least specific,
// looking for matches at each level. Note that a given level may
// have multiple attributes (e.g. IsWild() and IsNormal()).
@ -280,19 +243,19 @@ nsEffectiveTLDService::GetBaseDomainInternal(nsCString &aHostname,
return NS_ERROR_INVALID_ARG;
// Perform the lookup.
const ETLDEntry* entry = ETLDEntry::GetEntry(currDomain);
if (entry) {
if (entry->IsWild() && prevDomain) {
const int result = mGraph.Lookup(Substring(currDomain, end));
if (result != Dafsa::kKeyNotFound) {
if (result == kWildcardRule && prevDomain) {
// wildcard rules imply an eTLD one level inferior to the match.
eTLD = prevDomain;
break;
}
if (entry->IsNormal() || !nextDot) {
if ((result == kWildcardRule || result != kExceptionRule) || !nextDot) {
// specific match, or we've hit the top domain level
eTLD = currDomain;
break;
}
if (entry->IsException()) {
if (result == kExceptionRule) {
// exception rules imply an eTLD one level superior to the match.
eTLD = nextDot + 1;
break;
@ -343,6 +306,13 @@ nsEffectiveTLDService::GetBaseDomainInternal(nsCString &aHostname,
return NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS;
aBaseDomain = Substring(iter, end);
// Update the MRU table if in use.
if (entry) {
entry->mHost = aHostname;
entry->mBaseDomain = aBaseDomain;
}
// add on the trailing dot, if applicable
if (trailingDot)
aBaseDomain.Append('.');
@ -365,3 +335,13 @@ nsEffectiveTLDService::NormalizeHostname(nsCString &aHostname)
ToLowerCase(aHostname);
return NS_OK;
}
bool
nsEffectiveTLDService::LookupForAdd(const nsACString& aHost, TLDCacheEntry** aEntry)
{
MOZ_ASSERT(NS_IsMainThread());
const uint32_t hash = HashString(aHost.BeginReading(), aHost.Length());
*aEntry = &mMruTable[hash % kTableSize];
return (*aEntry)->mHost == aHost;
}

Просмотреть файл

@ -12,67 +12,11 @@
#include "nsString.h"
#include "nsCOMPtr.h"
#include "mozilla/Attributes.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/Dafsa.h"
#include "mozilla/MemoryReporting.h"
class nsIIDNService;
// struct for static data generated from effective_tld_names.dat
struct ETLDEntry {
friend class nsEffectiveTLDService;
public:
bool IsNormal() const { return wild || !exception; }
bool IsException() const { return exception; }
bool IsWild() const { return wild; }
const char* GetEffectiveTLDName() const
{
return strings.strtab + strtab_index;
}
static const ETLDEntry* GetEntry(const char* aDomain);
static const size_t ETLD_ENTRY_N_INDEX_BITS = 30;
// These fields must be public to allow static construction.
uint32_t strtab_index : ETLD_ENTRY_N_INDEX_BITS;
uint32_t exception : 1;
uint32_t wild : 1;
private:
struct Cmp {
int operator()(const ETLDEntry aEntry) const
{
return strcmp(mName, aEntry.GetEffectiveTLDName());
}
explicit Cmp(const char* aName) : mName(aName) {}
const char* mName;
};
#define ETLD_STR_NUM_1(line) str##line
#define ETLD_STR_NUM(line) ETLD_STR_NUM_1(line)
struct etld_string_list {
#define ETLD_ENTRY(name, ex, wild) char ETLD_STR_NUM(__LINE__)[sizeof(name)];
#include "etld_data.inc"
#undef ETLD_ENTRY
};
// This static string table is all the eTLD domain names packed together.
static const union etld_strings {
struct etld_string_list list;
char strtab[1];
} strings;
// This is the static entries table. Each entry has an index into the string
// table. The entries are in sorted order so that binary search can be used.
static const ETLDEntry entries[];
void FuncForStaticAsserts(void);
#undef ETLD_STR_NUM
#undef ETLD_STR_NUM1
};
class nsEffectiveTLDService final
: public nsIEffectiveTLDService
, public nsIMemoryReporter
@ -93,6 +37,40 @@ private:
~nsEffectiveTLDService();
nsCOMPtr<nsIIDNService> mIDNService;
// The DAFSA provides a compact encoding of the rather large eTLD list.
mozilla::Dafsa mGraph;
struct TLDCacheEntry
{
nsCString mHost;
nsCString mBaseDomain;
};
// We use a small most recently used cache to compensate for DAFSA lookups
// being slightly slower than a binary search on a larger table of strings.
//
// We first check the cache for a matching result and avoid a DAFSA lookup
// if a match is found. Otherwise we lookup the domain in the DAFSA and then
// cache the result. During standard browsing the same domains are repeatedly
// fed into |GetBaseDomainInternal| so this ends up being an effective
// mitigation getting about a 99% hit rate with four tabs open.
//
// A size of 31 is used rather than a more logical power-of-two such as 32
// since it is a prime number and provides fewer collisions when when used
// with our hash algorithms.
static const uint32_t kTableSize = 31;
TLDCacheEntry mMruTable[kTableSize];
/**
* Performs a lookup on the MRU table and provides a pointer to the hash
* entry that matched or should be used for adding this host.
*
* @param aHost The host to lookup.
* @param aEntry Out param, the entry in the MRU table to use.
* @return True if a match was found, false if there was a miss.
*/
inline bool LookupForAdd(const nsACString& aHost, TLDCacheEntry** aEntry);
};
#endif // EffectiveTLDService_h

Просмотреть файл

@ -4,6 +4,8 @@
import codecs
import encodings.idna
import imp
import os
import re
import sys
@ -34,12 +36,7 @@ def getEffectiveTLDs(path):
assert domain not in domains, \
"repeating domain %s makes no sense" % domain
domains.add(domain)
entries.append(entry)
# Sort the entries so we can use binary search on them.
entries.sort(key=EffectiveTLDEntry.domain)
return entries
yield entry
def _normalizeHostname(domain):
"""
@ -103,19 +100,37 @@ class EffectiveTLDEntry:
def main(output, effective_tld_filename):
"""
effective_tld_filename is the effective TLD file to parse.
A C++ array of { domain, exception, wild } entries representing the
A C++ array of a binary representation of a DAFSA representing the
eTLD file is then printed to output.
"""
def boolStr(b):
if b:
return "true"
return "false"
# Find and load the `make_dafsa.py` script under xpcom/ds.
tld_dir = os.path.dirname(effective_tld_filename)
make_dafsa_py = os.path.join(tld_dir, '../../xpcom/ds/make_dafsa.py')
sys.path.append(os.path.dirname(make_dafsa_py))
with open(make_dafsa_py, 'r') as fh:
make_dafsa = imp.load_module('script', fh, make_dafsa_py,
('.py', 'r', imp.PY_SOURCE))
for etld in getEffectiveTLDs(effective_tld_filename):
exception = boolStr(etld.exception())
wild = boolStr(etld.wild())
output.write('ETLD_ENTRY("%s", %s, %s)\n' % (etld.domain(), exception, wild))
def typeEnum(etld):
"""
Maps the flags to the DAFSA's enum types.
"""
if etld.exception():
return 1
elif etld.wild():
return 2
else:
return 0
def dafsa_words():
"""
make_dafsa expects lines of the form "<domain_name><enum_value>"
"""
for etld in getEffectiveTLDs(effective_tld_filename):
yield "%s%d" % (etld.domain(), typeEnum(etld))
output.write(make_dafsa.words_to_cxx(dafsa_words()))
if __name__ == '__main__':
main(sys.stdout, sys.argv[1])

Просмотреть файл

@ -2198,10 +2198,6 @@ xulrunner)
;;
esac
if test -n "$MOZ_B2G"; then
AC_DEFINE(MOZ_B2G)
fi
# Graphene is a desktop runtime for running applications with a HTML UI.
if test -n "$MOZ_GRAPHENE"; then
AC_DEFINE(MOZ_GRAPHENE)
@ -2219,9 +2215,7 @@ fi
AC_SUBST(MOZ_PHOENIX)
AC_SUBST(MOZ_XULRUNNER)
AC_SUBST(MOZ_B2G)
AC_SUBST(MOZ_MULET)
AC_SUBST(MOZ_B2G_VERSION)
dnl ========================================================
dnl Ensure Android SDK and build-tools versions depending on
@ -4025,10 +4019,6 @@ MOZ_ARG_DISABLE_BOOL(startupcache,
MOZ_DISABLE_STARTUPCACHE=1,
MOZ_DISABLE_STARTUPCACHE=)
dnl bug 988880: disable startup cache on b2g
if test -n "$MOZ_B2G"; then
MOZ_DISABLE_STARTUPCACHE=1
fi
if test -n "$MOZ_DISABLE_STARTUPCACHE"; then
AC_DEFINE(MOZ_DISABLE_STARTUPCACHE)
fi
@ -4742,10 +4732,6 @@ else
MOZ_APP_MAXVERSION=$MOZ_APP_VERSION
fi
MOZ_B2G_VERSION=${MOZ_B2G_VERSION:-"1.0.0"}
AC_DEFINE_UNQUOTED(MOZ_B2G_VERSION,"$MOZ_B2G_VERSION")
AC_DEFINE_UNQUOTED(MOZ_B2G_OS_NAME,"$MOZ_B2G_OS_NAME")
AC_SUBST(MOZ_APP_NAME)
AC_SUBST(MOZ_APP_REMOTINGNAME)
AC_SUBST(MOZ_APP_DISPLAYNAME)

Просмотреть файл

@ -827,16 +827,8 @@ CreateErrorText(const char16_t* aDescription,
NS_ENSURE_SUCCESS(rv, rv);
// XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$u, Column %4$u:
char16_t *message = nsTextFormatter::smprintf(msg.get(), aDescription,
aSourceURL, aLineNumber,
aColNumber);
if (!message) {
return NS_ERROR_OUT_OF_MEMORY;
}
aErrorString.Assign(message);
free(message);
nsTextFormatter::ssprintf(aErrorString, msg.get(), aDescription,
aSourceURL, aLineNumber, aColNumber);
return NS_OK;
}
@ -919,14 +911,9 @@ nsExpatDriver::HandleError()
"Expected", msg);
// . Expected: </%S>.
char16_t *message = nsTextFormatter::smprintf(msg.get(), tagName.get());
if (!message) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsAutoString message;
nsTextFormatter::ssprintf(message, msg.get(), tagName.get());
description.Append(message);
free(message);
}
// Adjust the column number so that it is one based rather than zero based.

Просмотреть файл

@ -79,13 +79,20 @@ SandboxBrokerPolicyFactory::SandboxBrokerPolicyFactory()
#endif
#ifdef MOZ_WIDGET_GTK
// Bug 1321134: DConf's single bit of shared memory
if (const auto userDir = g_get_user_runtime_dir()) {
// Bug 1321134: DConf's single bit of shared memory
// The leaf filename is "user" by default, but is configurable.
nsPrintfCString shmPath("%s/dconf/", userDir);
policy->AddPrefix(rdwrcr, shmPath.get());
#ifdef MOZ_PULSEAUDIO
// PulseAudio, if it can't get server info from X11, will break
// unless it can open this directory (or create it, but in our use
// case we know it already exists). See bug 1335329.
nsPrintfCString pulsePath("%s/pulse", userDir);
policy->AddPath(rdonly, pulsePath.get());
#endif // MOZ_PULSEAUDIO
}
#endif
#endif // MOZ_WIDGET_GTK
// Read permissions
policy->AddPath(rdonly, "/dev/urandom");
@ -111,6 +118,13 @@ SandboxBrokerPolicyFactory::SandboxBrokerPolicyFactory()
// Bug 1385715: NVIDIA PRIME support
policy->AddPath(rdonly, "/proc/modules");
#ifdef MOZ_PULSEAUDIO
// See bug 1384986 comment #1.
if (const auto xauth = PR_GetEnv("XAUTHORITY")) {
policy->AddPath(rdonly, xauth);
}
#endif
// Configuration dirs in the homedir that we want to allow read
// access to.
mozilla::Array<const char*, 3> confDirs = {

Просмотреть файл

@ -19,6 +19,8 @@ SOURCES += [
if CONFIG['MOZ_ALSA']:
DEFINES['MOZ_ALSA'] = True
if CONFIG['MOZ_PULSEAUDIO']:
DEFINES['MOZ_PULSEAUDIO'] = True
LOCAL_INCLUDES += [
'/security/sandbox/linux', # SandboxLogging.h, SandboxInfo.h

Просмотреть файл

@ -1,644 +0,0 @@
/* 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/. */
/**
* Temporary abstraction layer for common Fx Accounts operations.
* For now, we will be using this module only from B2G but in the end we might
* want this to be merged with FxAccounts.jsm and let other products also use
* it.
*/
"use strict";
this.EXPORTED_SYMBOLS = ["FxAccountsManager"];
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FxAccounts.jsm");
Cu.import("resource://gre/modules/FxAccountsCommon.js");
XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
"@mozilla.org/permissionmanager;1",
"nsIPermissionManager");
this.FxAccountsManager = {
init() {
Services.obs.addObserver(this, ONLOGOUT_NOTIFICATION);
Services.obs.addObserver(this, ON_FXA_UPDATE_NOTIFICATION);
},
observe(aSubject, aTopic, aData) {
// Both topics indicate our cache is invalid
this._activeSession = null;
if (aData == ONVERIFIED_NOTIFICATION) {
log.debug("FxAccountsManager: cache cleared, broadcasting: " + aData);
Services.obs.notifyObservers(null, aData);
}
},
// We don't really need to save fxAccounts instance but this way we allow
// to mock FxAccounts from tests.
_fxAccounts: fxAccounts,
// We keep the session details here so consumers don't need to deal with
// session tokens and are only required to handle the email.
_activeSession: null,
// Are we refreshing our authentication? If so, allow attempts to sign in
// while we are already signed in.
_refreshing: false,
// We only expose the email and the verified status so far.
get _user() {
if (!this._activeSession || !this._activeSession.email) {
return null;
}
return {
email: this._activeSession.email,
verified: this._activeSession.verified,
profile: this._activeSession.profile,
}
},
_error(aError, aDetails) {
log.error(aError);
let reason = {
error: aError
};
if (aDetails) {
reason.details = aDetails;
}
return Promise.reject(reason);
},
_getError(aServerResponse) {
if (!aServerResponse || !aServerResponse.error || !aServerResponse.error.errno) {
return null;
}
let error = SERVER_ERRNO_TO_ERROR[aServerResponse.error.errno];
return error;
},
_serverError(aServerResponse) {
let error = this._getError({ error: aServerResponse });
return this._error(error ? error : ERROR_SERVER_ERROR, aServerResponse);
},
// As with _fxAccounts, we don't really need this method, but this way we
// allow tests to mock FxAccountsClient. By default, we want to return the
// client used by the fxAccounts object because deep down they should have
// access to the same hawk request object which will enable them to share
// local clock skeq data.
_getFxAccountsClient() {
return this._fxAccounts.getAccountsClient();
},
_signInSignUp(aMethod, aEmail, aPassword, aFetchKeys) {
if (Services.io.offline) {
return this._error(ERROR_OFFLINE);
}
if (!aEmail) {
return this._error(ERROR_INVALID_EMAIL);
}
if (!aPassword) {
return this._error(ERROR_INVALID_PASSWORD);
}
// Check that there is no signed in account first.
if ((!this._refreshing) && this._activeSession) {
return this._error(ERROR_ALREADY_SIGNED_IN_USER, {
user: this._user
});
}
let client = this._getFxAccountsClient();
return this._fxAccounts.getSignedInUser().then(
user => {
if ((!this._refreshing) && user) {
return this._error(ERROR_ALREADY_SIGNED_IN_USER, {
user: this._user
});
}
return client[aMethod](aEmail, aPassword, aFetchKeys);
}
).then(
user => {
let error = this._getError(user);
if (!user || !user.uid || !user.sessionToken || error) {
return this._error(error ? error : ERROR_INTERNAL_INVALID_USER, {
user
});
}
// If the user object includes an email field, it may differ in
// capitalization from what we sent down. This is the server's
// canonical capitalization and should be used instead.
user.email = user.email || aEmail;
// If we're using server-side sign to refreshAuthentication
// we don't need to update local state; also because of two
// interacting glitches we need to bypass an event emission.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1031580
if (this._refreshing) {
return Promise.resolve({user: this._user});
}
return this._fxAccounts.setSignedInUser(user).then(
() => {
this._activeSession = user;
log.debug("User signed in: " + JSON.stringify(this._user) +
" - Account created " + (aMethod == "signUp"));
// There is no way to obtain the key fetch token afterwards
// without login out the user and asking her to log in again.
// Also, key fetch tokens are designed to be short-lived, so
// we need to fetch kB as soon as we have the key fetch token.
if (aFetchKeys) {
this._fxAccounts.getKeys();
}
return this._fxAccounts.getSignedInUserProfile().catch(error => {
// Not fetching the profile is sad but the FxA logs will already
// have noise.
return null;
});
}
).then(profile => {
if (profile) {
this._activeSession.profile = profile;
}
return Promise.resolve({
accountCreated: aMethod === "signUp",
user: this._user
});
});
},
reason => { return this._serverError(reason); }
);
},
/**
* Determine whether the incoming error means that the current account
* has new server-side state via deletion or password change, and if so,
* spawn the appropriate UI (sign in or refresh); otherwise re-reject.
*
* As of May 2014, the only HTTP call triggered by this._getAssertion()
* is to /certificate/sign via:
* FxAccounts.getAssertion()
* FxAccountsInternal.getCertificateSigned()
* FxAccountsClient.signCertificate()
* See the latter method for possible (error code, errno) pairs.
*/
_handleGetAssertionError(reason, aAudience, aPrincipal) {
log.debug("FxAccountsManager._handleGetAssertionError()");
let errno = (reason ? reason.errno : NaN) || NaN;
// If the previously valid email/password pair is no longer valid ...
if (errno == ERRNO_INVALID_AUTH_TOKEN) {
return this._fxAccounts.accountStatus().then(
(exists) => {
// ... if the email still maps to an account, the password
// must have changed, so ask the user to enter the new one ...
if (exists) {
return this.getAccount().then(
(user) => {
return this._refreshAuthentication(aAudience, user.email,
aPrincipal,
true /* logoutOnFailure */);
}
);
}
// ... otherwise, the account was deleted, so ask for Sign In/Up
return this._localSignOut().then(
() => {
return this._uiRequest(UI_REQUEST_SIGN_IN_FLOW, aAudience,
aPrincipal);
},
(reason) => {
// reject primary problem, not signout failure
log.error("Signing out in response to server error threw: " +
reason);
return this._error(reason);
}
);
}
);
}
return Promise.reject(reason.message ? { error: reason.message } : reason);
},
_getAssertion(aAudience, aPrincipal) {
return this._fxAccounts.getAssertion(aAudience).then(
(result) => {
if (aPrincipal) {
this._addPermission(aPrincipal);
}
return result;
},
(reason) => {
return this._handleGetAssertionError(reason, aAudience, aPrincipal);
}
);
},
/**
* "Refresh authentication" means:
* Interactively demonstrate knowledge of the FxA password
* for the currently logged-in account.
* There are two very different scenarios:
* 1) The password has changed on the server. Failure should log
* the current account OUT.
* 2) The person typing can't prove knowledge of the password used
* to log in. Failure should do nothing.
*/
_refreshAuthentication(aAudience, aEmail, aPrincipal,
logoutOnFailure = false) {
this._refreshing = true;
return this._uiRequest(UI_REQUEST_REFRESH_AUTH,
aAudience, aPrincipal, aEmail).then(
(assertion) => {
this._refreshing = false;
return assertion;
},
(reason) => {
this._refreshing = false;
if (logoutOnFailure) {
return this._signOut().then(
() => {
return this._error(reason);
}
);
}
return this._error(reason);
}
);
},
_localSignOut() {
return this._fxAccounts.signOut(true);
},
_signOut() {
if (!this._activeSession) {
return Promise.resolve();
}
// We clear the local session cache as soon as we get the onlogout
// notification triggered within FxAccounts.signOut, so we save the
// session token value to be able to remove the remote server session
// in case that we have network connection.
let sessionToken = this._activeSession.sessionToken;
return this._localSignOut().then(
() => {
// At this point the local session should already be removed.
// The client can create new sessions up to the limit (100?).
// Orphaned tokens on the server will eventually be garbage collected.
if (Services.io.offline) {
return Promise.resolve();
}
// Otherwise, we try to remove the remote session.
let client = this._getFxAccountsClient();
return client.signOut(sessionToken).then(
result => {
let error = this._getError(result);
if (error) {
return this._error(error, result);
}
log.debug("Signed out");
return Promise.resolve();
},
reason => {
return this._serverError(reason);
}
);
}
);
},
_uiRequest(aRequest, aAudience, aPrincipal, aParams) {
if (Services.io.offline) {
return this._error(ERROR_OFFLINE);
}
let ui = Cc["@mozilla.org/fxaccounts/fxaccounts-ui-glue;1"]
.createInstance(Ci.nsIFxAccountsUIGlue);
if (!ui[aRequest]) {
return this._error(ERROR_UI_REQUEST);
}
if (!aParams || !Array.isArray(aParams)) {
aParams = [aParams];
}
return ui[aRequest].apply(this, aParams).then(
result => {
// Even if we get a successful result from the UI, the account will
// most likely be unverified, so we cannot get an assertion.
if (result && result.verified) {
return this._getAssertion(aAudience, aPrincipal);
}
return this._error(ERROR_UNVERIFIED_ACCOUNT, {
user: result
});
},
error => {
return this._error(ERROR_UI_ERROR, error);
}
);
},
_addPermission(aPrincipal) {
// This will fail from tests cause we are running them in the child
// process until we have chrome tests in b2g. Bug 797164.
try {
permissionManager.addFromPrincipal(aPrincipal, FXACCOUNTS_PERMISSION,
Ci.nsIPermissionManager.ALLOW_ACTION);
} catch (e) {
log.warn("Could not add permission " + e);
}
},
// -- API --
signIn(aEmail, aPassword, aFetchKeys) {
return this._signInSignUp("signIn", aEmail, aPassword, aFetchKeys);
},
signUp(aEmail, aPassword, aFetchKeys) {
return this._signInSignUp("signUp", aEmail, aPassword, aFetchKeys);
},
signOut() {
if (!this._activeSession) {
// If there is no cached active session, we try to get it from the
// account storage.
return this.getAccount().then(
result => {
if (!result) {
return Promise.resolve();
}
return this._signOut();
}
);
}
return this._signOut();
},
resendVerificationEmail() {
return this._fxAccounts.resendVerificationEmail().then(
(result) => {
return result;
},
(error) => {
return this._error(ERROR_SERVER_ERROR, error);
}
);
},
getAccount() {
// We check first if we have session details cached.
if (this._activeSession) {
// If our cache says that the account is not yet verified,
// we kick off verification before returning what we have.
if (!this._activeSession.verified) {
this.verificationStatus(this._activeSession);
}
log.debug("Account " + JSON.stringify(this._user));
return Promise.resolve(this._user);
}
// If no cached information, we try to get it from the persistent storage.
return this._fxAccounts.getSignedInUser().then(
user => {
if (!user || !user.email) {
log.debug("No signed in account");
return Promise.resolve(null);
}
this._activeSession = user;
// If we get a stored information of a not yet verified account,
// we kick off verification before returning what we have.
if (!user.verified) {
this.verificationStatus(user);
// Trying to get the profile for unverified users will fail, so we
// don't even try in that case.
log.debug("Account ", this._user);
return Promise.resolve(this._user);
}
return this._fxAccounts.getSignedInUserProfile().then(profile => {
if (profile) {
this._activeSession.profile = profile;
}
log.debug("Account ", this._user);
return Promise.resolve(this._user);
}).catch(error => {
// FxAccounts logs already inform about the error.
log.debug("Account ", this._user);
return Promise.resolve(this._user);
});
}
);
},
queryAccount(aEmail) {
log.debug("queryAccount " + aEmail);
if (Services.io.offline) {
return this._error(ERROR_OFFLINE);
}
if (!aEmail) {
return this._error(ERROR_INVALID_EMAIL);
}
let client = this._getFxAccountsClient();
return client.accountExists(aEmail).then(
result => {
log.debug("Account " + (result ? "" : "does not ") + "exists");
let error = this._getError(result);
if (error) {
return this._error(error, result);
}
return Promise.resolve({
registered: result
});
},
reason => { this._serverError(reason); }
);
},
verificationStatus() {
log.debug("verificationStatus");
if (!this._activeSession || !this._activeSession.sessionToken) {
this._error(ERROR_NO_TOKEN_SESSION);
}
// There is no way to unverify an already verified account, so we just
// return the account details of a verified account
if (this._activeSession.verified) {
log.debug("Account already verified");
return;
}
if (Services.io.offline) {
log.warn("Offline; skipping verification.");
return;
}
let client = this._getFxAccountsClient();
client.recoveryEmailStatus(this._activeSession.sessionToken).then(
data => {
let error = this._getError(data);
if (error) {
this._error(error, data);
}
// If the verification status has changed, update state.
if (this._activeSession.verified != data.verified) {
this._activeSession.verified = data.verified;
this._fxAccounts.setSignedInUser(this._activeSession);
this._fxAccounts.getSignedInUserProfile().then(profile => {
if (profile) {
this._activeSession.profile = profile;
}
}).catch(error => {
// FxAccounts logs already inform about the error.
});
}
log.debug(JSON.stringify(this._user));
},
reason => { this._serverError(reason); }
);
},
/*
* Try to get an assertion for the given audience. Here we implement
* the heart of the response to navigator.mozId.request() on device.
* (We can also be called via the IAC API, but it's request() that
* makes this method complex.) The state machine looks like this,
* ignoring simple errors:
* If no one is signed in, and we aren't suppressing the UI:
* trigger the sign in flow.
* else if we were asked to refresh and the grace period is up:
* trigger the refresh flow.
* else:
* request user permission to share an assertion if we don't have it
* already and ask the core code for an assertion, which might itself
* trigger either the sign in or refresh flows (if our account
* changed on the server).
*
* aOptions can include:
* refreshAuthentication - (bool) Force re-auth.
* silent - (bool) Prevent any UI interaction.
* I.e., try to get an automatic assertion.
*/
getAssertion(aAudience, aPrincipal, aOptions) {
if (!aAudience) {
return this._error(ERROR_INVALID_AUDIENCE);
}
let principal = aPrincipal;
log.debug("FxAccountsManager.getAssertion() aPrincipal: ",
principal.origin, principal.appId,
principal.isInIsolatedMozBrowserElement);
return this.getAccount().then(
user => {
if (user) {
// Three have-user cases to consider. First: are we unverified?
if (!user.verified) {
return this._error(ERROR_UNVERIFIED_ACCOUNT, {
user
});
}
// Second case: do we need to refresh?
if (aOptions &&
(typeof(aOptions.refreshAuthentication) != "undefined")) {
let gracePeriod = aOptions.refreshAuthentication;
if (typeof(gracePeriod) !== "number" || isNaN(gracePeriod)) {
return this._error(ERROR_INVALID_REFRESH_AUTH_VALUE);
}
// Forcing refreshAuth to silent is a contradiction in terms,
// though it might succeed silently if we didn't reject here.
if (aOptions.silent) {
return this._error(ERROR_NO_SILENT_REFRESH_AUTH);
}
let secondsSinceAuth = (Date.now() / 1000) -
this._activeSession.authAt;
if (secondsSinceAuth > gracePeriod) {
return this._refreshAuthentication(aAudience, user.email,
principal,
false /* logoutOnFailure */);
}
}
// Third case: we are all set *locally*. Probably we just return
// the assertion, but the attempt might lead to the server saying
// we are deleted or have a new password, which will trigger a flow.
// Also we need to check if we have permission to get the assertion,
// otherwise we need to show the forceAuth UI to let the user know
// that the RP with no fxa permissions is trying to obtain an
// assertion. Once the user authenticates herself in the forceAuth UI
// the permission will be remembered by default.
let permission = permissionManager.testPermissionFromPrincipal(
principal,
FXACCOUNTS_PERMISSION
);
if (permission == Ci.nsIPermissionManager.PROMPT_ACTION &&
!this._refreshing) {
return this._refreshAuthentication(aAudience, user.email,
principal,
false /* logoutOnFailure */);
} else if (permission == Ci.nsIPermissionManager.DENY_ACTION &&
!this._refreshing) {
return this._error(ERROR_PERMISSION_DENIED);
} else if (this._refreshing) {
// If we are blocked asking for a password we should not continue
// the getAssertion process.
return Promise.resolve(null);
}
return this._getAssertion(aAudience, principal);
}
log.debug("No signed in user");
if (aOptions && aOptions.silent) {
return Promise.resolve(null);
}
return this._uiRequest(UI_REQUEST_SIGN_IN_FLOW, aAudience, principal);
}
);
},
getKeys() {
if (!Services.prefs.getBoolPref("services.sync.enabled", false)) {
return Promise.reject(ERROR_SYNC_DISABLED);
}
return this.getAccount().then(
user => {
if (!user) {
log.debug("No signed in user");
return Promise.resolve(null);
}
if (!user.verified) {
return this._error(ERROR_UNVERIFIED_ACCOUNT, {
user
});
}
return this._fxAccounts.getKeys();
}
);
}
};
FxAccountsManager.init();

Просмотреть файл

@ -31,9 +31,8 @@ this.FxAccountsStorageManager = function(options = {}) {
baseDir: options.baseDir || OS.Constants.Path.profileDir,
}
this.plainStorage = new JSONStorage(this.options);
// On b2g we have no loginManager for secure storage, and tests may want
// to pretend secure storage isn't available.
let useSecure = "useSecure" in options ? options.useSecure : haveLoginManager;
// Tests may want to pretend secure storage isn't available.
let useSecure = "useSecure" in options ? options.useSecure : true;
if (useSecure) {
this.secureStorage = new LoginManagerStorage();
} else {
@ -601,9 +600,3 @@ LoginManagerStorage.prototype = {
return null;
},
}
// A global variable to indicate if the login manager is available - it doesn't
// exist on b2g. Defined here as the use of preprocessor directives skews line
// numbers in the runtime, meaning stack-traces etc end up off by a few lines.
// Doing it at the end of the file makes that less of a pita.
var haveLoginManager = !AppConstants.MOZ_B2G;

Просмотреть файл

@ -32,7 +32,3 @@ EXTRA_JS_MODULES += [
'FxAccountsStorage.jsm',
'FxAccountsWebChannel.jsm',
]
# For now, we will only be using the FxA manager in B2G.
if CONFIG['MOZ_B2G']:
EXTRA_JS_MODULES += ['FxAccountsManager.jsm']

Просмотреть файл

@ -7,8 +7,7 @@
with Files("**"):
BUG_COMPONENT = ("Core", "XPCOM")
if not CONFIG['MOZ_B2G']:
TEST_DIRS += ['test']
TEST_DIRS += ['test']
XPIDL_SOURCES += [
'nsIStartupCache.idl',

Просмотреть файл

@ -40,13 +40,12 @@ doc-upload:
worker:
docker-image: {in-tree: "lint"}
max-run-time: 1800
taskcluster-proxy: true
run:
using: run-task
command: >
cd /home/worker/checkouts/gecko &&
./mach doc-upload --bucket gecko-docs.mozilla.org --region us-west-2
command: cd /home/worker/checkouts/gecko && ./mach doc-upload
scopes:
- secrets:get:project/releng/gecko/build/level-3/gecko-docs-upload
- secrets:get:project/releng/gecko/build/level-{level}/gecko-docs-upload
when:
files-changed:
- '**/*.py'

Просмотреть файл

@ -34,6 +34,8 @@ def common_setup(config, job, taskdesc):
if run['checkout']:
support_vcs_checkout(config, job, taskdesc)
taskdesc['worker'].setdefault('env', {})['MOZ_SCM_LEVEL'] = config.params['level']
@run_job_using("docker-worker", "run-task", schema=run_task_schema)
def docker_worker_run_task(config, job, taskdesc):

Просмотреть файл

@ -57,7 +57,9 @@ task_description_schema = Schema({
Optional('routes'): [basestring],
# custom scopes for this task; any scopes required for the worker will be
# added automatically
# added automatically. The following parameters will be substituted in each
# scope:
# {level} -- the scm level of this push
Optional('scopes'): [basestring],
# Tags
@ -950,11 +952,12 @@ def add_index_routes(config, tasks):
@transforms.add
def build_task(config, tasks):
for task in tasks:
worker_type = task['worker-type'].format(level=str(config.params['level']))
level = str(config.params['level'])
worker_type = task['worker-type'].format(level=level)
provisioner_id, worker_type = worker_type.split('/', 1)
routes = task.get('routes', [])
scopes = task.get('scopes', [])
scopes = [s.format(level=level) for s in task.get('scopes', [])]
# set up extra
extra = task.get('extra', {})

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше