mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 619494 - Make IndexedDB work in IPC Fennec. r=bent,mfinkle
This commit is contained in:
parent
d100392a5b
commit
0c39bea133
@ -120,7 +120,12 @@ CheckPermissionsHelper::Run()
|
||||
|
||||
nsresult rv;
|
||||
if (mHasPrompted) {
|
||||
if (permission != nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
// Add permissions to the database, but only if we are in the parent
|
||||
// process (if we are in the child process, we have already
|
||||
// set the permission when the prompt was shown in the parent, as
|
||||
// we cannot set the permission from the child).
|
||||
if (permission != nsIPermissionManager::UNKNOWN_ACTION &&
|
||||
XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), mASCIIOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
@ -180,7 +181,12 @@ CheckQuotaHelper::Run()
|
||||
|
||||
nsresult rv;
|
||||
if (mHasPrompted) {
|
||||
if (mPromptResult != nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
// Add permissions to the database, but only if we are in the parent
|
||||
// process (if we are in the child process, we have already
|
||||
// set the permission when the prompt was shown in the parent, as
|
||||
// we cannot set the permission from the child).
|
||||
if (mPromptResult != nsIPermissionManager::UNKNOWN_ACTION &&
|
||||
XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), mOrigin);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -37,12 +37,15 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "IDBFactory.h"
|
||||
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIScriptContext.h"
|
||||
|
||||
#include "mozilla/storage.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -54,6 +57,7 @@
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCID.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "AsyncConnectionHelper.h"
|
||||
#include "CheckPermissionsHelper.h"
|
||||
@ -62,6 +66,7 @@
|
||||
#include "IDBKeyRange.h"
|
||||
#include "IndexedDatabaseManager.h"
|
||||
#include "LazyIdleThread.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
#define PREF_INDEXEDDB_QUOTA "dom.indexedDB.warningQuota"
|
||||
|
||||
@ -76,6 +81,8 @@ USING_INDEXEDDB_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
GeckoProcessType gAllowedProcessType = GeckoProcessType_Invalid;
|
||||
|
||||
PRUintn gCurrentDatabaseIndex = BAD_TLS_INDEX;
|
||||
|
||||
PRInt32 gIndexedDBQuota = DEFAULT_QUOTA;
|
||||
@ -357,12 +364,7 @@ CreateDatabaseConnection(const nsACString& aASCIIOrigin,
|
||||
aDatabaseFilePath.Truncate();
|
||||
|
||||
nsCOMPtr<nsIFile> dbDirectory;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(dbDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dbDirectory->Append(NS_LITERAL_STRING("indexedDB"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsresult rv = IDBFactory::GetDirectory(getter_AddRefs(dbDirectory));
|
||||
|
||||
PRBool exists;
|
||||
rv = dbDirectory->Exists(&exists);
|
||||
@ -509,6 +511,11 @@ CreateDatabaseConnection(const nsACString& aASCIIOrigin,
|
||||
|
||||
} // anonyomous namespace
|
||||
|
||||
IDBFactory::IDBFactory()
|
||||
{
|
||||
IDBFactory::NoteUsedByProcessType(XRE_GetProcessType());
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIIDBFactory>
|
||||
IDBFactory::Create(nsPIDOMWindow* aWindow)
|
||||
@ -620,17 +627,45 @@ IDBFactory::GetIndexedDBQuota()
|
||||
return PRUint32(PR_MAX(gIndexedDBQuota, 0));
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
IDBFactory::NoteUsedByProcessType(GeckoProcessType aProcessType)
|
||||
{
|
||||
if (gAllowedProcessType == GeckoProcessType_Invalid) {
|
||||
gAllowedProcessType = aProcessType;
|
||||
} else if (aProcessType != gAllowedProcessType) {
|
||||
NS_RUNTIMEABORT("More than one process type is accessing IndexedDB!");
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBFactory::GetDirectory(nsIFile** aDirectory)
|
||||
{
|
||||
nsresult rv;
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aDirectory);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = (*aDirectory)->Append(NS_LITERAL_STRING("indexedDB"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
nsCOMPtr<nsILocalFile> localDirectory =
|
||||
do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||
rv = localDirectory->InitWithPath(
|
||||
ContentChild::GetSingleton()->GetIndexedDBPath());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
localDirectory.forget((nsILocalFile**)aDirectory);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
IDBFactory::GetDirectoryForOrigin(const nsACString& aASCIIOrigin,
|
||||
nsIFile** aDirectory)
|
||||
{
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = directory->Append(NS_LITERAL_STRING("indexedDB"));
|
||||
nsresult rv = GetDirectory(getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ConvertASCIItoUTF16 originSanitized(aASCIIOrigin);
|
||||
@ -820,6 +855,14 @@ IDBFactory::Open(const nsAString& aName,
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
// Force ContentChild to cache the path from the parent, so that
|
||||
// we do not end up in a side thread that asks for the path (which
|
||||
// would make ContentChild try to send a message in a thread other
|
||||
// than the main one).
|
||||
ContentChild::GetSingleton()->GetIndexedDBPath();
|
||||
}
|
||||
|
||||
if (aName.IsEmpty()) {
|
||||
return NS_ERROR_DOM_INDEXEDDB_NON_TRANSIENT_ERR;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "nsIIDBFactory.h"
|
||||
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
|
||||
@ -73,6 +74,16 @@ public:
|
||||
static PRUint32
|
||||
GetIndexedDBQuota();
|
||||
|
||||
// Called when a process uses an IndexedDB factory. We only allow
|
||||
// a single process type to use IndexedDB - the chrome/single process
|
||||
// in Firefox, and the child process in Fennec - so access by more
|
||||
// than one process type is a very serious error.
|
||||
static void
|
||||
NoteUsedByProcessType(GeckoProcessType aProcessType);
|
||||
|
||||
static nsresult
|
||||
GetDirectory(nsIFile** aDirectory);
|
||||
|
||||
static nsresult
|
||||
GetDirectoryForOrigin(const nsACString& aASCIIOrigin,
|
||||
nsIFile** aDirectory);
|
||||
@ -89,7 +100,7 @@ public:
|
||||
ObjectStoreInfoArray& aObjectStores);
|
||||
|
||||
private:
|
||||
IDBFactory() { }
|
||||
IDBFactory();
|
||||
~IDBFactory() { }
|
||||
|
||||
nsCOMPtr<nsIWeakReference> mWindow;
|
||||
|
@ -118,4 +118,6 @@ ifdef ENABLE_TESTS
|
||||
DIRS += test
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
@ -112,6 +112,8 @@ using namespace mozilla::docshell;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
nsString* gIndexedDBPath = nsnull;
|
||||
|
||||
class MemoryReportRequestChild : public PMemoryReportRequestChild
|
||||
{
|
||||
public:
|
||||
@ -229,6 +231,8 @@ ContentChild::ContentChild()
|
||||
|
||||
ContentChild::~ContentChild()
|
||||
{
|
||||
delete gIndexedDBPath;
|
||||
gIndexedDBPath = nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -670,5 +674,16 @@ ContentChild::RecvFlushMemory(const nsString& reason)
|
||||
return true;
|
||||
}
|
||||
|
||||
nsString&
|
||||
ContentChild::GetIndexedDBPath()
|
||||
{
|
||||
if (!gIndexedDBPath) {
|
||||
gIndexedDBPath = new nsString(); // cleaned up in the destructor
|
||||
SendGetIndexedDBDirectory(gIndexedDBPath);
|
||||
}
|
||||
|
||||
return *gIndexedDBPath;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -149,6 +149,10 @@ public:
|
||||
gfxIntSize GetScreenSize() { return mScreenSize; }
|
||||
#endif
|
||||
|
||||
// Get the directory for IndexedDB files. We query the parent for this and
|
||||
// cache the value
|
||||
nsString &GetIndexedDBPath();
|
||||
|
||||
private:
|
||||
NS_OVERRIDE
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
@ -68,6 +68,8 @@
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsConsoleMessage.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "IDBFactory.h"
|
||||
#if defined(MOZ_SYDNEYAUDIO)
|
||||
#include "AudioParent.h"
|
||||
#endif
|
||||
@ -437,6 +439,24 @@ ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissio
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvGetIndexedDBDirectory(nsString* aDirectory)
|
||||
{
|
||||
indexedDB::IDBFactory::NoteUsedByProcessType(GeckoProcessType_Content);
|
||||
|
||||
nsCOMPtr<nsIFile> dbDirectory;
|
||||
nsresult rv = indexedDB::IDBFactory::GetDirectory(getter_AddRefs(dbDirectory));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to get IndexedDB directory");
|
||||
return true;
|
||||
}
|
||||
|
||||
dbDirectory->GetPath(*aDirectory);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvSetClipboardText(const nsString& text, const PRInt32& whichClipboard)
|
||||
{
|
||||
|
@ -157,6 +157,9 @@ private:
|
||||
void EnsurePrefService();
|
||||
|
||||
virtual bool RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions);
|
||||
|
||||
virtual bool RecvGetIndexedDBDirectory(nsString* aDirectory);
|
||||
|
||||
virtual bool RecvSetClipboardText(const nsString& text, const PRInt32& whichClipboard);
|
||||
virtual bool RecvGetClipboardText(const PRInt32& whichClipboard, nsString* text);
|
||||
virtual bool RecvEmptyClipboard();
|
||||
|
@ -101,6 +101,7 @@ LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../src/base \
|
||||
-I$(srcdir)/../src/storage \
|
||||
-I$(srcdir)/../../xpcom/base \
|
||||
-I$(srcdir)/../indexedDB \
|
||||
-I$(topsrcdir)/extensions/cookie \
|
||||
$(NULL)
|
||||
|
||||
|
@ -183,6 +183,8 @@ parent:
|
||||
// nsIPermissionManager messages
|
||||
sync ReadPermissions() returns (Permission[] permissions);
|
||||
|
||||
sync GetIndexedDBDirectory() returns (nsString directory);
|
||||
|
||||
// These clipboard methods are only really used on Android since
|
||||
// the clipboard is not available in the content process.
|
||||
SetClipboardText(nsString text, PRInt32 whichClipboard);
|
||||
|
@ -567,7 +567,7 @@ pref("notification.feature.enabled", true);
|
||||
|
||||
// prevent tooltips from showing up
|
||||
pref("browser.chrome.toolbar_tips", false);
|
||||
pref("indexedDB.feature.enabled", false);
|
||||
pref("indexedDB.feature.enabled", true);
|
||||
|
||||
// prevent video elements from preloading too much data
|
||||
pref("media.preload.default", 1); // default to preload none
|
||||
|
78
mobile/chrome/content/IndexedDB.js
Normal file
78
mobile/chrome/content/IndexedDB.js
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Helper class for IndexedDB, parent part. Listens to
|
||||
* messages from the child and shows prompts for them.
|
||||
*/
|
||||
let IndexedDB = {
|
||||
_permissionsPrompt: "indexedDB-permissions-prompt",
|
||||
_permissionsResponse: "indexedDB-permissions-response",
|
||||
|
||||
_quotaPrompt: "indexedDB-quota-prompt",
|
||||
_quotaResponse: "indexedDB-quota-response",
|
||||
_quotaCancel: "indexedDB-quota-cancel",
|
||||
|
||||
_notificationIcon: "indexedDB-notification-icon",
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "IndexedDB:Prompt":
|
||||
this.showPrompt(aMessage);
|
||||
}
|
||||
},
|
||||
|
||||
showPrompt: function(aMessage) {
|
||||
let browser = aMessage.target;
|
||||
let payload = aMessage.json;
|
||||
let host = payload.host;
|
||||
let topic = payload.topic;
|
||||
let type;
|
||||
|
||||
if (topic == this._permissionsPrompt) {
|
||||
type = "indexedDB";
|
||||
payload.responseTopic = this._permissionsResponse;
|
||||
} else if (topic == this._quotaPrompt) {
|
||||
type = "indexedDBQuota";
|
||||
payload.responseTopic = this._quotaResponse;
|
||||
} else if (topic == this._quotaCancel) {
|
||||
payload.permission = Ci.nsIPermissionManager.UNKNOWN_ACTION;
|
||||
browser.messageManager.sendAsyncMessage("IndexedDB:Response", payload);
|
||||
// XXX Need to actually save this?
|
||||
return;
|
||||
}
|
||||
|
||||
let prompt = Cc["@mozilla.org/content-permission/prompt;1"].createInstance(Ci.nsIContentPermissionPrompt);
|
||||
|
||||
// If the user waits a long time before responding, we default to UNKNOWN_ACTION.
|
||||
let timeoutId = setTimeout(function() {
|
||||
payload.permission = Ci.nsIPermissionManager.UNKNOWN_ACTION;
|
||||
browser.messageManager.sendAsyncMessage("IndexedDB:Response", payload);
|
||||
timeoutId = null;
|
||||
}, 30000);
|
||||
|
||||
function checkTimeout() {
|
||||
if (timeoutId === null) return true;
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
prompt.prompt({
|
||||
type: type,
|
||||
uri: Services.io.newURI(payload.location, null, null),
|
||||
window: null,
|
||||
element: aMessage.target,
|
||||
|
||||
cancel: function() {
|
||||
if (checkTimeout()) return;
|
||||
payload.permission = Ci.nsIPermissionManager.DENY_ACTION;
|
||||
browser.messageManager.sendAsyncMessage("IndexedDB:Response", payload);
|
||||
},
|
||||
|
||||
allow: function() {
|
||||
if (checkTimeout()) return;
|
||||
payload.permission = Ci.nsIPermissionManager.ALLOW_ACTION;
|
||||
browser.messageManager.sendAsyncMessage("IndexedDB:Response", payload);
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
@ -453,3 +453,80 @@ let ContentActive = {
|
||||
};
|
||||
|
||||
ContentActive.init();
|
||||
|
||||
/**
|
||||
* Helper class for IndexedDB, child part. Listens using
|
||||
* the observer service for events regarding IndexedDB
|
||||
* prompts, and sends messages to the parent to actually
|
||||
* show the prompts.
|
||||
*/
|
||||
let IndexedDB = {
|
||||
_permissionsPrompt: "indexedDB-permissions-prompt",
|
||||
_permissionsResponse: "indexedDB-permissions-response",
|
||||
|
||||
_quotaPrompt: "indexedDB-quota-prompt",
|
||||
_quotaResponse: "indexedDB-quota-response",
|
||||
_quotaCancel: "indexedDB-quota-cancel",
|
||||
|
||||
waitingObservers: [],
|
||||
|
||||
init: function IndexedDBPromptHelper_init() {
|
||||
let os = Services.obs;
|
||||
os.addObserver(this, this._permissionsPrompt, false);
|
||||
os.addObserver(this, this._quotaPrompt, false);
|
||||
os.addObserver(this, this._quotaCancel, false);
|
||||
addMessageListener("IndexedDB:Response", this);
|
||||
},
|
||||
|
||||
observe: function IndexedDBPromptHelper_observe(aSubject, aTopic, aData) {
|
||||
if (aTopic != this._permissionsPrompt && aTopic != this._quotaPrompt && aTopic != this._quotaCancel) {
|
||||
throw new Error("Unexpected topic!");
|
||||
}
|
||||
|
||||
let requestor = aSubject.QueryInterface(Ci.nsIInterfaceRequestor);
|
||||
let observer = requestor.getInterface(Ci.nsIObserver);
|
||||
|
||||
let contentWindow = requestor.getInterface(Ci.nsIDOMWindow);
|
||||
let contentDocument = contentWindow.document;
|
||||
|
||||
if (aTopic == this._quotaCancel) {
|
||||
observer.observe(null, this._quotaResponse, Ci.nsIPermissionManager.UNKNOWN_ACTION);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remote to parent
|
||||
sendAsyncMessage("IndexedDB:Prompt", {
|
||||
topic: aTopic,
|
||||
host: contentDocument.documentURIObject.asciiHost,
|
||||
location: contentDocument.location.toString(),
|
||||
data: aData,
|
||||
observerId: this.addWaitingObserver(observer),
|
||||
});
|
||||
},
|
||||
|
||||
receiveMessage: function(aMessage) {
|
||||
let payload = aMessage.json;
|
||||
switch (aMessage.name) {
|
||||
case "IndexedDB:Response":
|
||||
let observer = this.getAndRemoveWaitingObserver(payload.observerId);
|
||||
observer.observe(null, payload.responseTopic, payload.permission);
|
||||
}
|
||||
},
|
||||
|
||||
addWaitingObserver: function(aObserver) {
|
||||
let observerId = 0;
|
||||
while (observerId in this.waitingObservers)
|
||||
observerId++;
|
||||
this.waitingObservers[observerId] = aObserver;
|
||||
return observerId;
|
||||
},
|
||||
|
||||
getAndRemoveWaitingObserver: function(aObserverId) {
|
||||
let observer = this.waitingObservers[aObserverId];
|
||||
delete this.waitingObservers[aObserverId];
|
||||
return observer;
|
||||
},
|
||||
};
|
||||
|
||||
IndexedDB.init();
|
||||
|
||||
|
@ -100,6 +100,7 @@ XPCOMUtils.defineLazyGetter(this, "CommonUI", function() {
|
||||
["ExtensionsView", "chrome://browser/content/extensions.js"],
|
||||
["MenuListHelperUI", "chrome://browser/content/MenuListHelperUI.js"],
|
||||
["OfflineApps", "chrome://browser/content/OfflineApps.js"],
|
||||
["IndexedDB", "chrome://browser/content/IndexedDB.js"],
|
||||
["PreferencesView", "chrome://browser/content/preferences.js"],
|
||||
["Sanitizer", "chrome://browser/content/sanitize.js"],
|
||||
["SelectHelperUI", "chrome://browser/content/SelectHelperUI.js"],
|
||||
|
@ -487,6 +487,11 @@ var BrowserUI = {
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// Only load IndexedDB.js when we actually need it. A general fix will happen in bug 647079.
|
||||
messageManager.addMessageListener("IndexedDB:Prompt", function(aMessage) {
|
||||
return IndexedDB.receiveMessage(aMessage);
|
||||
});
|
||||
|
||||
// Delay the panel UI and Sync initialization.
|
||||
window.addEventListener("UIReadyDelayed", function(aEvent) {
|
||||
window.removeEventListener(aEvent.type, arguments.callee, false);
|
||||
|
@ -29,6 +29,7 @@ chrome.jar:
|
||||
content/BookmarkHelper.js (content/BookmarkHelper.js)
|
||||
content/BookmarkPopup.js (content/BookmarkPopup.js)
|
||||
* content/ContextCommands.js (content/ContextCommands.js)
|
||||
content/IndexedDB.js (content/IndexedDB.js)
|
||||
content/MenuListHelperUI.js (content/MenuListHelperUI.js)
|
||||
content/OfflineApps.js (content/OfflineApps.js)
|
||||
content/SelectHelperUI.js (content/SelectHelperUI.js)
|
||||
|
@ -29,7 +29,8 @@ function setPagePermission(type, uri, allow) {
|
||||
pm.add(uri, type, Ci.nsIPermissionManager.DENY_ACTION);
|
||||
}
|
||||
|
||||
const kEntities = { "geolocation": "geolocation", "desktop-notification": "desktopNotification" };
|
||||
const kEntities = { "geolocation": "geolocation", "desktop-notification": "desktopNotification",
|
||||
"indexedDB": "offlineApps", "indexedDBQuota": "indexedDBQuota" };
|
||||
|
||||
function ContentPermissionPrompt() {}
|
||||
|
||||
|
@ -164,6 +164,15 @@ offlineApps.allow=Allow
|
||||
offlineApps.never=Don't Allow
|
||||
offlineApps.notNow=Not Now
|
||||
|
||||
# New-style ContentPermissionPrompt values
|
||||
offlineApps.dontAllow=Don't Allow
|
||||
offlineApps.siteWantsTo=%S wants to store data on your computer for offline use.
|
||||
|
||||
# IndexedDB Quota increases
|
||||
indexedDBQuota.allow=Allow
|
||||
indexedDBQuota.dontAllow=Don't Allow
|
||||
indexedDBQuota.siteWantsTo=%S wants to store a lot of data on your computer for offline use.
|
||||
|
||||
# Bookmark List
|
||||
bookmarkList.desktop=Desktop Bookmarks
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user