mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge b-i to m-c.
This commit is contained in:
commit
d7e49cc136
@ -821,8 +821,10 @@ pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
|
||||
|
||||
// enable Skia/GL (OpenGL-accelerated 2D drawing) for large enough 2d canvases,
|
||||
// falling back to Skia/software for smaller canvases
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
pref("gfx.canvas.azure.backends", "skia");
|
||||
pref("gfx.canvas.azure.accelerated", true);
|
||||
#endif
|
||||
|
||||
// Turn on dynamic cache size for Skia
|
||||
pref("gfx.canvas.skiagl.dynamic-cache", true);
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "514b47fbaae1c65d566c557a4c2c99d40de4cf3e",
|
||||
"revision": "5cc15d1e291050f4e46c91b87a1af1353d1c5e46",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -1895,6 +1895,12 @@ public:
|
||||
*/
|
||||
static bool IsUserFocusIgnored(nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Returns if aContent has the 'scrollgrab' property.
|
||||
* aContent may be null (in this case false is returned).
|
||||
*/
|
||||
static bool HasScrollgrab(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Flushes the layout tree (recursively)
|
||||
*
|
||||
|
@ -5919,6 +5919,13 @@ nsContentUtils::IsUserFocusIgnored(nsINode* aNode)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::HasScrollgrab(nsIContent* aContent)
|
||||
{
|
||||
nsGenericHTMLElement* element = nsGenericHTMLElement::FromContentOrNull(aContent);
|
||||
return element && element->Scrollgrab();
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::FlushLayoutForTree(nsIDOMWindow* aWindow)
|
||||
{
|
||||
|
@ -20,7 +20,14 @@ function IsD2DEnabled() {
|
||||
}
|
||||
|
||||
function IsLinux() {
|
||||
return navigator.platform.indexOf("Linux") == 0 &&
|
||||
var os = "";
|
||||
|
||||
try {
|
||||
os = Cc["@mozilla.org/xre/app-info;1"]
|
||||
.getService(SpecialPowers.Ci.nsIXULRuntime).OS;
|
||||
} catch (e) {}
|
||||
|
||||
return os.indexOf("Linux") == 0 &&
|
||||
navigator.appVersion.indexOf("Android") == -1;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsError.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsRuleData.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
#include "nsPresState.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
@ -1815,6 +1816,15 @@ nsGenericHTMLElement::GetURIAttr(nsIAtom* aAttr, nsIAtom* aBaseAttr, nsIURI** aU
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsGenericHTMLElement::IsScrollGrabAllowed(JSContext*, JSObject*)
|
||||
{
|
||||
// Only allow scroll grabbing in chrome and certified apps.
|
||||
nsIPrincipal* prin = nsContentUtils::GetSubjectPrincipal();
|
||||
return nsContentUtils::IsSystemPrincipal(prin) ||
|
||||
prin->GetAppStatus() == nsIPrincipal::APP_STATUS_CERTIFIED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetURIListAttr(nsIAtom* aAttr, nsAString& aResult)
|
||||
{
|
||||
|
@ -57,7 +57,8 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase,
|
||||
{
|
||||
public:
|
||||
nsGenericHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElementBase(aNodeInfo)
|
||||
: nsGenericHTMLElementBase(aNodeInfo),
|
||||
mScrollgrab(false)
|
||||
{
|
||||
NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
|
||||
"Unexpected namespace");
|
||||
@ -226,6 +227,14 @@ public:
|
||||
: NS_LITERAL_STRING("false"),
|
||||
aError);
|
||||
}
|
||||
bool Scrollgrab() const
|
||||
{
|
||||
return mScrollgrab;
|
||||
}
|
||||
void SetScrollgrab(bool aValue)
|
||||
{
|
||||
mScrollgrab = aValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether an attribute is an event (onclick, etc.)
|
||||
@ -930,6 +939,9 @@ public:
|
||||
tag == nsGkAtoms::object;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsScrollGrabAllowed(JSContext*, JSObject*);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Add/remove this element to the documents name cache
|
||||
@ -1226,6 +1238,8 @@ protected:
|
||||
|
||||
private:
|
||||
void ChangeEditableState(int32_t aChange);
|
||||
|
||||
bool mScrollgrab;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -962,24 +962,24 @@ this.DOMApplicationRegistry = {
|
||||
mm: aMm,
|
||||
refCount: 1
|
||||
});
|
||||
}
|
||||
|
||||
// If it wasn't registered before, let's update its state
|
||||
if ((aMsgName === 'Webapps:FireEvent') ||
|
||||
(aMsgName === 'Webapps:UpdateState')) {
|
||||
if (man) {
|
||||
let app = this.getAppByManifestURL(aApp.manifestURL);
|
||||
if (app && ((aApp.installState !== app.installState) ||
|
||||
(aApp.downloading !== app.downloading))) {
|
||||
debug("Got a registration from an outdated app: " +
|
||||
aApp.manifestURL);
|
||||
let aEvent ={
|
||||
type: app.installState,
|
||||
app: app,
|
||||
manifestURL: app.manifestURL,
|
||||
manifest: app.manifest
|
||||
};
|
||||
aMm.sendAsyncMessage(aMsgName, aEvent);
|
||||
}
|
||||
// If the state reported by the registration is outdated, update it now.
|
||||
if ((aMsgName === 'Webapps:FireEvent') ||
|
||||
(aMsgName === 'Webapps:UpdateState')) {
|
||||
if (man) {
|
||||
let app = this.getAppByManifestURL(aApp.manifestURL);
|
||||
if (app && ((aApp.installState !== app.installState) ||
|
||||
(aApp.downloading !== app.downloading))) {
|
||||
debug("Got a registration from an outdated app: " +
|
||||
aApp.manifestURL);
|
||||
let aEvent ={
|
||||
type: app.installState,
|
||||
app: app,
|
||||
manifestURL: app.manifestURL,
|
||||
manifest: app.manifest
|
||||
};
|
||||
aMm.sendAsyncMessage(aMsgName, aEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10070,7 +10070,19 @@ class CGJSImplClass(CGBindingImplClass):
|
||||
descriptor.name)
|
||||
constructorBody = "SetIsDOMBinding();"
|
||||
extradefinitions= string.Template(
|
||||
"NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(${ifaceName}, mImpl, mParent)\n"
|
||||
"NS_IMPL_CYCLE_COLLECTION_CLASS(${ifaceName})\n"
|
||||
"NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(${ifaceName})\n"
|
||||
" NS_IMPL_CYCLE_COLLECTION_UNLINK(mImpl)\n"
|
||||
" NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)\n"
|
||||
" NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER\n"
|
||||
" tmp->ClearWeakReferences();\n"
|
||||
"NS_IMPL_CYCLE_COLLECTION_UNLINK_END\n"
|
||||
"NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(${ifaceName})\n"
|
||||
" NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)\n"
|
||||
" NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)\n"
|
||||
" NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS\n"
|
||||
"NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END\n"
|
||||
"NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(${ifaceName})\n"
|
||||
"NS_IMPL_CYCLE_COLLECTING_ADDREF(${ifaceName})\n"
|
||||
"NS_IMPL_CYCLE_COLLECTING_RELEASE(${ifaceName})\n"
|
||||
"NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(${ifaceName})\n"
|
||||
|
@ -25,14 +25,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=717103
|
||||
devicestorage_setup();
|
||||
|
||||
var oldFiles = ["a.png", "b.png", "c.png"];
|
||||
var timeFile = "t.png";
|
||||
var newFiles = ["d.png", "e.png", "f.png"];
|
||||
|
||||
var storage = navigator.getDeviceStorage('pictures');
|
||||
var prefix = "devicestorage/" + randomFilename(12);
|
||||
var callback;
|
||||
var files;
|
||||
var i;
|
||||
var timestamp;
|
||||
var lastFileAddedTimestamp;
|
||||
|
||||
function verifyAndDelete(prefix, files, e) {
|
||||
if (e.target.result == null) {
|
||||
@ -62,31 +62,56 @@ function verifyAndDelete(prefix, files, e) {
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
files.remove(index);
|
||||
files.splice(index, 1);
|
||||
|
||||
// clean up
|
||||
var cleanup = storage.delete(e.target.result.name);
|
||||
cleanup.onsuccess = function(e) {}
|
||||
}
|
||||
|
||||
function addSuccess(e) {
|
||||
i = i + 1;
|
||||
if (i == files.length) {
|
||||
callback();
|
||||
return;
|
||||
function addFile(filename, callback) {
|
||||
var addReq = storage.addNamed(createRandomBlob('image/png'), prefix + '/' + filename);
|
||||
addReq.onsuccess = function(e) {
|
||||
// After adding the file, we go ahead and grab the timestamp of the file
|
||||
// that we just added
|
||||
var getReq = storage.get(prefix + '/' + filename);
|
||||
getReq.onsuccess = function(e) {
|
||||
lastFileAddedTimestamp = e.target.result.lastModifiedDate;
|
||||
callback();
|
||||
}
|
||||
getReq.onerror = function(e) {
|
||||
ok(false, "getError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
};
|
||||
}
|
||||
addReq.onerror = function(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
}
|
||||
addFile(files[i]);
|
||||
}
|
||||
|
||||
function addError(e) {
|
||||
ok(false, "addError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
function addFileArray(fileArray, callback) {
|
||||
var i = 0;
|
||||
function addNextFile() {
|
||||
i = i + 1;
|
||||
if (i == fileArray.length) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
addFile(fileArray[i], addNextFile);
|
||||
}
|
||||
addFile(fileArray[0], addNextFile);
|
||||
}
|
||||
|
||||
function addFile(filename){
|
||||
var req = storage.addNamed(createRandomBlob('image/png'), prefix + '/' + files[i]);
|
||||
req.onsuccess = addSuccess;
|
||||
req.onerror = addError;
|
||||
function delFile(filename, callback) {
|
||||
var req = storage.delete(prefix + '/' + filename);
|
||||
req.onsuccess = function(e) {
|
||||
callback();
|
||||
};
|
||||
req.onerror = function(e) {
|
||||
ok(false, "delError was called : " + e.target.error.name);
|
||||
devicestorage_cleanup();
|
||||
};
|
||||
}
|
||||
|
||||
function afterNewFiles() {
|
||||
@ -103,27 +128,36 @@ function afterNewFiles() {
|
||||
};
|
||||
}
|
||||
|
||||
function addNewFiles() {
|
||||
i = 0;
|
||||
files = newFiles;
|
||||
callback = afterNewFiles;
|
||||
addFile(files[0]);
|
||||
}
|
||||
|
||||
function beforeNewFiles() {
|
||||
timestamp = new Date();
|
||||
setTimeout(addNewFiles, 1000);
|
||||
function waitForTimestampChange() {
|
||||
// We've added a new file. See if the timestamp differs from
|
||||
// oldFileAddedTimestamp, and if it's the same wait for a bit
|
||||
// and try again.
|
||||
if (lastFileAddedTimestamp.valueOf() === timestamp.valueOf()) {
|
||||
delFile(timeFile, function() {
|
||||
setTimeout(function() {
|
||||
addFile(timeFile, waitForTimestampChange);
|
||||
}, 1000);
|
||||
});
|
||||
} else {
|
||||
timestamp = lastFileAddedTimestamp;
|
||||
// The timestamp has changed. Go ahead and add the rest of the new files
|
||||
delFile(timeFile, function() {
|
||||
addFileArray(newFiles, afterNewFiles);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function afterOldFiles() {
|
||||
setTimeout(beforeNewFiles, 1000);
|
||||
timestamp = lastFileAddedTimestamp;
|
||||
setTimeout(function() {
|
||||
// We've added our old files and waited for a second.
|
||||
// Add a new file until the timestamp changes
|
||||
addFile(timeFile, waitForTimestampChange);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function addOldFiles() {
|
||||
i = 0;
|
||||
files = oldFiles;
|
||||
callback = afterOldFiles;
|
||||
addFile(files[0]);
|
||||
addFileArray(oldFiles, afterOldFiles);
|
||||
}
|
||||
|
||||
addOldFiles();
|
||||
|
@ -121,10 +121,6 @@ using namespace mozilla::system;
|
||||
#include "BluetoothService.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
#include "ipc/Nuwa.h"
|
||||
#endif
|
||||
|
||||
#include "JavaScriptParent.h"
|
||||
|
||||
#ifdef MOZ_B2G_FM
|
||||
@ -140,8 +136,6 @@ using namespace mozilla::system;
|
||||
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
||||
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
|
||||
|
||||
#define NUWA_FORK_WAIT_DURATION_MS 2000 // 2 seconds.
|
||||
|
||||
using base::ChildPrivileges;
|
||||
using base::KillProcess;
|
||||
using namespace mozilla::dom::bluetooth;
|
||||
@ -273,32 +267,16 @@ static bool sCanLaunchSubprocesses;
|
||||
// The first content child has ID 1, so the chrome process can have ID 0.
|
||||
static uint64_t gContentChildID = 1;
|
||||
|
||||
|
||||
// sNuwaProcess points to the Nuwa process which is used for forking new
|
||||
// processes later.
|
||||
static StaticRefPtr<ContentParent> sNuwaProcess;
|
||||
// Nuwa process is ready for creating new process.
|
||||
static bool sNuwaReady = false;
|
||||
// The array containing the preallocated processes. 4 as the inline storage size
|
||||
// should be enough so we don't need to grow the nsAutoTArray.
|
||||
static StaticAutoPtr<nsAutoTArray<nsRefPtr<ContentParent>, 4> > sSpareProcesses;
|
||||
static StaticAutoPtr<nsTArray<CancelableTask*> > sNuwaForkWaitTasks;
|
||||
|
||||
// We want the prelaunched process to know that it's for apps, but not
|
||||
// actually for any app in particular. Use a magic manifest URL.
|
||||
// Can't be a static constant.
|
||||
#define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}")
|
||||
|
||||
void
|
||||
/* static */ already_AddRefed<ContentParent>
|
||||
ContentParent::RunNuwaProcess()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sNuwaProcess) {
|
||||
NS_RUNTIMEABORT("sNuwaProcess is created twice.");
|
||||
}
|
||||
|
||||
sNuwaProcess =
|
||||
nsRefPtr<ContentParent> nuwaProcess =
|
||||
new ContentParent(/* aApp = */ nullptr,
|
||||
/* aIsForBrowser = */ false,
|
||||
/* aIsForPreallocated = */ true,
|
||||
@ -307,109 +285,10 @@ ContentParent::RunNuwaProcess()
|
||||
base::PRIVILEGES_INHERIT,
|
||||
PROCESS_PRIORITY_BACKGROUND,
|
||||
/* aIsNuwaProcess = */ true);
|
||||
sNuwaProcess->Init();
|
||||
nuwaProcess->Init();
|
||||
return nuwaProcess.forget();
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// initialization off the critical path of app startup.
|
||||
static CancelableTask* sPreallocateAppProcessTask;
|
||||
// This number is fairly arbitrary ... the intention is to put off
|
||||
// launching another app process until the last one has finished
|
||||
// loading its content, to reduce CPU/memory/IO contention.
|
||||
static int sPreallocateDelayMs = 1000;
|
||||
|
||||
static void
|
||||
DelayedNuwaFork()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
sPreallocateAppProcessTask = nullptr;
|
||||
|
||||
if (!sNuwaReady) {
|
||||
if (!sNuwaProcess) {
|
||||
ContentParent::RunNuwaProcess();
|
||||
}
|
||||
// else sNuwaProcess is starting. It will SendNuwaFork() when ready.
|
||||
} else if (sSpareProcesses->IsEmpty()) {
|
||||
sNuwaProcess->SendNuwaFork();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ScheduleDelayedNuwaFork()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sPreallocateAppProcessTask) {
|
||||
// Make sure there is only one request running.
|
||||
return;
|
||||
}
|
||||
|
||||
sPreallocateAppProcessTask = NewRunnableFunction(DelayedNuwaFork);
|
||||
MessageLoop::current()->
|
||||
PostDelayedTask(FROM_HERE,
|
||||
sPreallocateAppProcessTask,
|
||||
sPreallocateDelayMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a spare ContentParent from sSpareProcesses list.
|
||||
*/
|
||||
static already_AddRefed<ContentParent>
|
||||
GetSpareProcess()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sSpareProcesses->IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ContentParent> process = sSpareProcesses->LastElement();
|
||||
sSpareProcesses->RemoveElementAt(sSpareProcesses->Length() - 1);
|
||||
|
||||
if (sSpareProcesses->IsEmpty() && sNuwaReady) {
|
||||
NS_ASSERTION(sNuwaProcess != nullptr,
|
||||
"Nuwa process is not present!");
|
||||
ScheduleDelayedNuwaFork();
|
||||
}
|
||||
|
||||
return process.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a ContentParent to spare process list.
|
||||
*/
|
||||
static void
|
||||
PublishSpareProcess(ContentParent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sNuwaForkWaitTasks->IsEmpty()) {
|
||||
sNuwaForkWaitTasks->ElementAt(0)->Cancel();
|
||||
sNuwaForkWaitTasks->RemoveElementAt(0);
|
||||
}
|
||||
|
||||
sSpareProcesses->AppendElement(aContent);
|
||||
}
|
||||
|
||||
static void
|
||||
MaybeForgetSpare(ContentParent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (sSpareProcesses->RemoveElement(aContent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aContent == sNuwaProcess) {
|
||||
sNuwaProcess = nullptr;
|
||||
sNuwaReady = false;
|
||||
ScheduleDelayedNuwaFork();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// PreallocateAppProcess is called by the PreallocatedProcessManager.
|
||||
// ContentParent then takes this process back within
|
||||
// MaybeTakePreallocatedAppProcess.
|
||||
@ -433,11 +312,7 @@ ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
|
||||
ChildPrivileges aPrivs,
|
||||
ProcessPriority aInitialPriority)
|
||||
{
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
nsRefPtr<ContentParent> process = GetSpareProcess();
|
||||
#else
|
||||
nsRefPtr<ContentParent> process = PreallocatedProcessManager::Take();
|
||||
#endif
|
||||
if (!process) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -464,17 +339,8 @@ ContentParent::StartUp()
|
||||
|
||||
sCanLaunchSubprocesses = true;
|
||||
|
||||
sSpareProcesses = new nsAutoTArray<nsRefPtr<ContentParent>, 4>();
|
||||
ClearOnShutdown(&sSpareProcesses);
|
||||
|
||||
sNuwaForkWaitTasks = new nsTArray<CancelableTask*>();
|
||||
ClearOnShutdown(&sNuwaForkWaitTasks);
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
ScheduleDelayedNuwaFork();
|
||||
#else
|
||||
// Try to preallocate a process that we can transform into an app later.
|
||||
PreallocatedProcessManager::AllocateAfterDelay();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
@ -1027,25 +893,13 @@ ContentParent::MarkAsDead()
|
||||
mIsAlive = false;
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::OnNuwaForkTimeout()
|
||||
{
|
||||
if (!sNuwaForkWaitTasks->IsEmpty()) {
|
||||
sNuwaForkWaitTasks->RemoveElementAt(0);
|
||||
}
|
||||
|
||||
// We haven't RecvAddNewProcess() after SendNuwaFork(). Maybe the main
|
||||
// thread of the Nuwa process is in deadlock.
|
||||
MOZ_ASSERT(false, "Can't fork from the nuwa process.");
|
||||
}
|
||||
|
||||
void
|
||||
ContentParent::OnChannelError()
|
||||
{
|
||||
nsRefPtr<ContentParent> content(this);
|
||||
PContentParent::OnChannelError();
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
MaybeForgetSpare(this);
|
||||
PreallocatedProcessManager::MaybeForgetSpare(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1801,19 +1655,12 @@ ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
|
||||
bool
|
||||
ContentParent::RecvFirstIdle()
|
||||
{
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
if (sSpareProcesses->IsEmpty() && sNuwaReady) {
|
||||
ScheduleDelayedNuwaFork();
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
// When the ContentChild goes idle, it sends us a FirstIdle message
|
||||
// which we use as a good time to prelaunch another process. If we
|
||||
// prelaunch any sooner than this, then we'll be competing with the
|
||||
// child process and slowing it down.
|
||||
PreallocatedProcessManager::AllocateAfterDelay();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1897,34 +1744,16 @@ ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::SendNuwaFork()
|
||||
{
|
||||
if (this != sNuwaProcess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CancelableTask* nuwaForkTimeoutTask = NewRunnableMethod(
|
||||
this, &ContentParent::OnNuwaForkTimeout);
|
||||
sNuwaForkWaitTasks->AppendElement(nuwaForkTimeoutTask);
|
||||
|
||||
MessageLoop::current()->
|
||||
PostDelayedTask(FROM_HERE,
|
||||
nuwaForkTimeoutTask,
|
||||
NUWA_FORK_WAIT_DURATION_MS);
|
||||
|
||||
return PContentParent::SendNuwaFork();
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvNuwaReady()
|
||||
{
|
||||
NS_ASSERTION(!sNuwaReady, "Multiple Nuwa processes created!");
|
||||
ProcessPriorityManager::SetProcessPriority(sNuwaProcess,
|
||||
hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
sNuwaReady = true;
|
||||
SendNuwaFork();
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
PreallocatedProcessManager::OnNuwaReady();
|
||||
return true;
|
||||
#else
|
||||
NS_ERROR("ContentParent::RecvNuwaReady() not implemented!");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1939,7 +1768,7 @@ ContentParent::RecvAddNewProcess(const uint32_t& aPid,
|
||||
aFds,
|
||||
base::PRIVILEGES_DEFAULT);
|
||||
content->Init();
|
||||
PublishSpareProcess(content);
|
||||
PreallocatedProcessManager::PublishSpareProcess(content);
|
||||
return true;
|
||||
#else
|
||||
NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
*/
|
||||
static already_AddRefed<ContentParent> PreallocateAppProcess();
|
||||
|
||||
static void RunNuwaProcess();
|
||||
static already_AddRefed<ContentParent> RunNuwaProcess();
|
||||
|
||||
/**
|
||||
* Get or create a content process for the given TabContext. aFrameElement
|
||||
@ -209,8 +209,6 @@ public:
|
||||
return PContentParent::RecvPJavaScriptConstructor(aActor);
|
||||
}
|
||||
|
||||
virtual bool SendNuwaFork();
|
||||
|
||||
protected:
|
||||
void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
|
||||
virtual void ActorDestroy(ActorDestroyReason why);
|
||||
|
@ -9,6 +9,19 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "ProcessPriorityManager.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsCxPusher.h"
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
#include "ipc/Nuwa.h"
|
||||
#endif
|
||||
|
||||
// This number is fairly arbitrary ... the intention is to put off
|
||||
// launching another app process until the last one has finished
|
||||
// loading its content, to reduce CPU/memory/IO contention.
|
||||
#define DEFAULT_ALLOCATE_DELAY 1000
|
||||
#define NUWA_FORK_WAIT_DURATION_MS 2000 // 2 seconds.
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::hal;
|
||||
@ -35,6 +48,31 @@ public:
|
||||
void AllocateNow();
|
||||
already_AddRefed<ContentParent> Take();
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
public:
|
||||
void ScheduleDelayedNuwaFork();
|
||||
void DelayedNuwaFork();
|
||||
void PublishSpareProcess(ContentParent* aContent);
|
||||
void MaybeForgetSpare(ContentParent* aContent);
|
||||
void OnNuwaReady();
|
||||
already_AddRefed<ContentParent> GetSpareProcess();
|
||||
|
||||
private:
|
||||
void OnNuwaForkTimeout();
|
||||
void NuwaFork();
|
||||
|
||||
// initialization off the critical path of app startup.
|
||||
CancelableTask* mPreallocateAppProcessTask;
|
||||
|
||||
// The array containing the preallocated processes. 4 as the inline storage size
|
||||
// should be enough so we don't need to grow the nsAutoTArray.
|
||||
nsAutoTArray<nsRefPtr<ContentParent>, 4> mSpareProcesses;
|
||||
nsTArray<CancelableTask*> mNuwaForkWaitTasks;
|
||||
|
||||
// Nuwa process is ready for creating new process.
|
||||
bool mIsNuwaReady;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
|
||||
|
||||
@ -72,6 +110,10 @@ NS_IMPL_ISUPPORTS1(PreallocatedProcessManagerImpl, nsIObserver)
|
||||
|
||||
PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
|
||||
: mEnabled(false)
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
, mPreallocateAppProcessTask(nullptr)
|
||||
, mIsNuwaReady(false)
|
||||
#endif
|
||||
{}
|
||||
|
||||
void
|
||||
@ -127,7 +169,11 @@ PreallocatedProcessManagerImpl::Enable()
|
||||
}
|
||||
|
||||
mEnabled = true;
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
ScheduleDelayedNuwaFork();
|
||||
#else
|
||||
AllocateAfterDelay();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -140,7 +186,8 @@ PreallocatedProcessManagerImpl::AllocateAfterDelay()
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateOnIdle),
|
||||
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs", 1000));
|
||||
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
|
||||
DEFAULT_ALLOCATE_DELAY));
|
||||
}
|
||||
|
||||
void
|
||||
@ -165,6 +212,135 @@ PreallocatedProcessManagerImpl::AllocateNow()
|
||||
mPreallocatedAppProcess = ContentParent::PreallocateAppProcess();
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::ScheduleDelayedNuwaFork()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mPreallocateAppProcessTask) {
|
||||
// Make sure there is only one request running.
|
||||
return;
|
||||
}
|
||||
|
||||
mPreallocateAppProcessTask = NewRunnableMethod(
|
||||
this, &PreallocatedProcessManagerImpl::DelayedNuwaFork);
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE, mPreallocateAppProcessTask,
|
||||
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
|
||||
DEFAULT_ALLOCATE_DELAY));
|
||||
}
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::DelayedNuwaFork()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mPreallocateAppProcessTask = nullptr;
|
||||
|
||||
if (!mIsNuwaReady) {
|
||||
if (!mPreallocatedAppProcess) {
|
||||
mPreallocatedAppProcess = ContentParent::RunNuwaProcess();
|
||||
}
|
||||
// else mPreallocatedAppProcess is starting. It will NuwaFork() when ready.
|
||||
} else if (mSpareProcesses.IsEmpty()) {
|
||||
NuwaFork();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a spare ContentParent from mSpareProcesses list.
|
||||
*/
|
||||
already_AddRefed<ContentParent>
|
||||
PreallocatedProcessManagerImpl::GetSpareProcess()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mSpareProcesses.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<ContentParent> process = mSpareProcesses.LastElement();
|
||||
mSpareProcesses.RemoveElementAt(mSpareProcesses.Length() - 1);
|
||||
|
||||
if (mSpareProcesses.IsEmpty() && mIsNuwaReady) {
|
||||
NS_ASSERTION(mPreallocatedAppProcess != nullptr,
|
||||
"Nuwa process is not present!");
|
||||
ScheduleDelayedNuwaFork();
|
||||
}
|
||||
|
||||
return process.forget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish a ContentParent to spare process list.
|
||||
*/
|
||||
void
|
||||
PreallocatedProcessManagerImpl::PublishSpareProcess(ContentParent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mNuwaForkWaitTasks.IsEmpty()) {
|
||||
mNuwaForkWaitTasks.ElementAt(0)->Cancel();
|
||||
mNuwaForkWaitTasks.RemoveElementAt(0);
|
||||
}
|
||||
|
||||
mSpareProcesses.AppendElement(aContent);
|
||||
}
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::MaybeForgetSpare(ContentParent* aContent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mSpareProcesses.RemoveElement(aContent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aContent == mPreallocatedAppProcess) {
|
||||
mPreallocatedAppProcess = nullptr;
|
||||
mIsNuwaReady = false;
|
||||
ScheduleDelayedNuwaFork();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::OnNuwaReady()
|
||||
{
|
||||
NS_ASSERTION(!mIsNuwaReady, "Multiple Nuwa processes created!");
|
||||
ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess,
|
||||
hal::PROCESS_PRIORITY_FOREGROUND);
|
||||
mIsNuwaReady = true;
|
||||
NuwaFork();
|
||||
}
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::OnNuwaForkTimeout()
|
||||
{
|
||||
if (!mNuwaForkWaitTasks.IsEmpty()) {
|
||||
mNuwaForkWaitTasks.RemoveElementAt(0);
|
||||
}
|
||||
|
||||
// We haven't RecvAddNewProcess() after NuwaFork(). Maybe the main
|
||||
// thread of the Nuwa process is in deadlock.
|
||||
MOZ_ASSERT(false, "Can't fork from the nuwa process.");
|
||||
}
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::NuwaFork()
|
||||
{
|
||||
CancelableTask* nuwaForkTimeoutTask = NewRunnableMethod(
|
||||
this, &PreallocatedProcessManagerImpl::OnNuwaForkTimeout);
|
||||
mNuwaForkWaitTasks.AppendElement(nuwaForkTimeoutTask);
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
nuwaForkTimeoutTask,
|
||||
NUWA_FORK_WAIT_DURATION_MS);
|
||||
mPreallocatedAppProcess->SendNuwaFork();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
PreallocatedProcessManagerImpl::Disable()
|
||||
{
|
||||
@ -174,8 +350,24 @@ PreallocatedProcessManagerImpl::Disable()
|
||||
|
||||
mEnabled = false;
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
// Cancel pending fork.
|
||||
if (mPreallocateAppProcessTask) {
|
||||
mPreallocateAppProcessTask->Cancel();
|
||||
mPreallocateAppProcessTask = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mPreallocatedAppProcess) {
|
||||
mPreallocatedAppProcess->ShutDown();
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
while (mSpareProcesses.Length() > 0){
|
||||
nsRefPtr<ContentParent> process = mSpareProcesses[0];
|
||||
process->Close();
|
||||
mSpareProcesses.RemoveElementAt(0);
|
||||
}
|
||||
mIsNuwaReady = false;
|
||||
#endif
|
||||
mPreallocatedAppProcess->Close();
|
||||
mPreallocatedAppProcess = nullptr;
|
||||
}
|
||||
}
|
||||
@ -199,6 +391,11 @@ PreallocatedProcessManagerImpl::ObserveProcessShutdown(nsISupports* aSubject)
|
||||
}
|
||||
}
|
||||
|
||||
inline PreallocatedProcessManagerImpl* GetPPMImpl()
|
||||
{
|
||||
return PreallocatedProcessManagerImpl::Singleton();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace mozilla {
|
||||
@ -206,25 +403,53 @@ namespace mozilla {
|
||||
/* static */ void
|
||||
PreallocatedProcessManager::AllocateAfterDelay()
|
||||
{
|
||||
PreallocatedProcessManagerImpl::Singleton()->AllocateAfterDelay();
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
GetPPMImpl()->ScheduleDelayedNuwaFork();
|
||||
#else
|
||||
GetPPMImpl()->AllocateAfterDelay();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PreallocatedProcessManager::AllocateOnIdle()
|
||||
{
|
||||
PreallocatedProcessManagerImpl::Singleton()->AllocateOnIdle();
|
||||
GetPPMImpl()->AllocateOnIdle();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PreallocatedProcessManager::AllocateNow()
|
||||
{
|
||||
PreallocatedProcessManagerImpl::Singleton()->AllocateNow();
|
||||
GetPPMImpl()->AllocateNow();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<ContentParent>
|
||||
PreallocatedProcessManager::Take()
|
||||
{
|
||||
return PreallocatedProcessManagerImpl::Singleton()->Take();
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
return GetPPMImpl()->GetSpareProcess();
|
||||
#else
|
||||
return GetPPMImpl()->Take();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
/* static */ void
|
||||
PreallocatedProcessManager::PublishSpareProcess(ContentParent* aContent)
|
||||
{
|
||||
GetPPMImpl()->PublishSpareProcess(aContent);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PreallocatedProcessManager::MaybeForgetSpare(ContentParent* aContent)
|
||||
{
|
||||
GetPPMImpl()->MaybeForgetSpare(aContent);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PreallocatedProcessManager::OnNuwaReady()
|
||||
{
|
||||
GetPPMImpl()->OnNuwaReady();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -78,6 +78,12 @@ public:
|
||||
*/
|
||||
static already_AddRefed<ContentParent> Take();
|
||||
|
||||
#ifdef MOZ_NUWA_PROCESS
|
||||
static void PublishSpareProcess(ContentParent* aContent);
|
||||
static void MaybeForgetSpare(ContentParent* aContent);
|
||||
static void OnNuwaReady();
|
||||
#endif
|
||||
|
||||
private:
|
||||
PreallocatedProcessManager();
|
||||
DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);
|
||||
|
@ -829,7 +829,6 @@ RTCError.prototype = {
|
||||
// This is a separate object because we don't want to expose it to DOM.
|
||||
function PeerConnectionObserver() {
|
||||
this._dompc = null;
|
||||
this._guard = new WeakReferent(this);
|
||||
}
|
||||
PeerConnectionObserver.prototype = {
|
||||
classDescription: "PeerConnectionObserver",
|
||||
@ -1127,20 +1126,6 @@ PeerConnectionObserver.prototype = {
|
||||
getSupportedConstraints: function(dict) {
|
||||
return dict;
|
||||
},
|
||||
|
||||
get weakReferent() {
|
||||
return this._guard;
|
||||
}
|
||||
};
|
||||
|
||||
// A PeerConnectionObserver member that c++ can do weak references on
|
||||
|
||||
function WeakReferent(parent) {
|
||||
this._parent = parent; // prevents parent from going away without us
|
||||
}
|
||||
WeakReferent.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
|
||||
|
@ -23,7 +23,7 @@ dictionary MmsDeliveryInfo
|
||||
// |delivery| = "received" or not yet delivered).
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(3593c914-420a-11e3-a297-a3bdd768257f)]
|
||||
[scriptable, builtinclass, uuid(82ca2465-f967-4107-a4da-65b7a15d5dba)]
|
||||
interface nsIDOMMozMmsMessage : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -71,5 +71,5 @@ interface nsIDOMMozMmsMessage : nsISupports
|
||||
// manually downloaded.
|
||||
|
||||
// Request read report from sender or not.
|
||||
readonly attribute boolean isReadReportRequested;
|
||||
readonly attribute boolean readReportRequested;
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ interface nsIDOMMozSmsSegmentInfo;
|
||||
#define MOBILE_MESSAGE_SERVICE_CONTRACTID "@mozilla.org/mobilemessage/mobilemessageservice;1"
|
||||
%}
|
||||
|
||||
[scriptable, builtinclass, uuid(c9a1aa14-7088-4f22-9d7f-b0c6ce9cf484)]
|
||||
[scriptable, builtinclass, uuid(7255f557-0dd1-42f9-82fa-031cebb76bb5)]
|
||||
interface nsIMobileMessageService : nsISupports
|
||||
{
|
||||
[implicit_jscontext]
|
||||
@ -45,7 +45,7 @@ interface nsIMobileMessageService : nsISupports
|
||||
in DOMString smil,
|
||||
in jsval attachments,
|
||||
in jsval expiryDate,
|
||||
in boolean isReadReportRequested);
|
||||
in boolean readReportRequested);
|
||||
|
||||
nsIDOMMozSmsSegmentInfo createSmsSegmentInfo(in long segments,
|
||||
in long charsPerSegment,
|
||||
|
@ -47,7 +47,7 @@ MmsMessage::MmsMessage(int32_t aId,
|
||||
const nsAString& aSmil,
|
||||
const nsTArray<MmsAttachment>& aAttachments,
|
||||
uint64_t aExpiryDate,
|
||||
bool aIsReadReportRequested)
|
||||
bool aReadReportRequested)
|
||||
: mId(aId),
|
||||
mThreadId(aThreadId),
|
||||
mIccId(aIccId),
|
||||
@ -61,7 +61,7 @@ MmsMessage::MmsMessage(int32_t aId,
|
||||
mSmil(aSmil),
|
||||
mAttachments(aAttachments),
|
||||
mExpiryDate(aExpiryDate),
|
||||
mIsReadReportRequested(aIsReadReportRequested)
|
||||
mReadReportRequested(aReadReportRequested)
|
||||
{
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ MmsMessage::MmsMessage(const mobilemessage::MmsMessageData& aData)
|
||||
, mSubject(aData.subject())
|
||||
, mSmil(aData.smil())
|
||||
, mExpiryDate(aData.expiryDate())
|
||||
, mIsReadReportRequested(aData.isReadReportRequested())
|
||||
, mReadReportRequested(aData.readReportRequested())
|
||||
{
|
||||
uint32_t len = aData.attachments().Length();
|
||||
mAttachments.SetCapacity(len);
|
||||
@ -339,7 +339,7 @@ MmsMessage::GetData(ContentParent* aParent,
|
||||
aData.subject() = mSubject;
|
||||
aData.smil() = mSmil;
|
||||
aData.expiryDate() = mExpiryDate;
|
||||
aData.isReadReportRequested() = mIsReadReportRequested;
|
||||
aData.readReportRequested() = mReadReportRequested;
|
||||
|
||||
aData.deliveryInfo().SetCapacity(mDeliveryInfo.Length());
|
||||
for (uint32_t i = 0; i < mDeliveryInfo.Length(); i++) {
|
||||
@ -658,9 +658,9 @@ MmsMessage::GetExpiryDate(JSContext* cx, JS::Value* aDate)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MmsMessage::GetIsReadReportRequested(bool* aIsReadReportRequested)
|
||||
MmsMessage::GetReadReportRequested(bool* aReadReportRequested)
|
||||
{
|
||||
*aIsReadReportRequested = mIsReadReportRequested;
|
||||
*aReadReportRequested = mReadReportRequested;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
const nsAString& aSmil,
|
||||
const nsTArray<idl::MmsAttachment>& aAttachments,
|
||||
uint64_t aExpiryDate,
|
||||
bool aIsReadReportRequested);
|
||||
bool aReadReportRequested);
|
||||
|
||||
MmsMessage(const mobilemessage::MmsMessageData& aData);
|
||||
|
||||
@ -57,7 +57,7 @@ public:
|
||||
const nsAString& aSmil,
|
||||
const JS::Value& aAttachments,
|
||||
const JS::Value& aExpiryDate,
|
||||
bool aIsReadReportRequested,
|
||||
bool aReadReportRequested,
|
||||
JSContext* aCx,
|
||||
nsIDOMMozMmsMessage** aMessage);
|
||||
|
||||
@ -79,7 +79,7 @@ private:
|
||||
nsString mSmil;
|
||||
nsTArray<idl::MmsAttachment> mAttachments;
|
||||
uint64_t mExpiryDate;
|
||||
bool mIsReadReportRequested;
|
||||
bool mReadReportRequested;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -74,7 +74,7 @@ MobileMessageService::CreateMmsMessage(int32_t aId,
|
||||
const nsAString& aSmil,
|
||||
const JS::Value& aAttachments,
|
||||
const JS::Value& aExpiryDate,
|
||||
bool aIsReadReportRequested,
|
||||
bool aReadReportRequested,
|
||||
JSContext* aCx,
|
||||
nsIDOMMozMmsMessage** aMessage)
|
||||
{
|
||||
@ -91,7 +91,7 @@ MobileMessageService::CreateMmsMessage(int32_t aId,
|
||||
aSmil,
|
||||
aAttachments,
|
||||
aExpiryDate,
|
||||
aIsReadReportRequested,
|
||||
aReadReportRequested,
|
||||
aCx,
|
||||
aMessage);
|
||||
}
|
||||
|
@ -1290,7 +1290,7 @@ MobileMessageDatabaseService.prototype = {
|
||||
if (headers["x-mms-expiry"] != undefined) {
|
||||
expiryDate = aMessageRecord.timestamp + headers["x-mms-expiry"] * 1000;
|
||||
}
|
||||
let isReadReportRequested = headers["x-mms-read-report"] || false;
|
||||
let readReportRequested = headers["x-mms-read-report"] || false;
|
||||
return gMobileMessageService.createMmsMessage(aMessageRecord.id,
|
||||
aMessageRecord.threadId,
|
||||
aMessageRecord.iccId,
|
||||
@ -1304,7 +1304,7 @@ MobileMessageDatabaseService.prototype = {
|
||||
smil,
|
||||
attachments,
|
||||
expiryDate,
|
||||
isReadReportRequested);
|
||||
readReportRequested);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -68,7 +68,7 @@ struct MmsMessageData
|
||||
nsString smil;
|
||||
MmsAttachmentData[] attachments;
|
||||
uint64_t expiryDate;
|
||||
bool isReadReportRequested;
|
||||
bool readReportRequested;
|
||||
};
|
||||
|
||||
union MobileMessageData
|
||||
|
@ -16,7 +16,7 @@ Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
|
||||
Cu.importGlobalProperties(["indexedDB"]);
|
||||
|
||||
const DB_NAME = "net_stats";
|
||||
const DB_VERSION = 3;
|
||||
const DB_VERSION = 4;
|
||||
const STORE_NAME = "net_stats";
|
||||
|
||||
// Constant defining the maximum values allowed per interface. If more, older
|
||||
@ -92,6 +92,34 @@ NetworkStatsDB.prototype = {
|
||||
if (DEBUG) {
|
||||
debug("Created object stores and indexes for version 3");
|
||||
}
|
||||
} else if (currVersion == 3) {
|
||||
// Delete redundent indexes (leave "network" only).
|
||||
objectStore = aTransaction.objectStore(STORE_NAME);
|
||||
if (objectStore.indexNames.contains("appId")) {
|
||||
objectStore.deleteIndex("appId");
|
||||
}
|
||||
if (objectStore.indexNames.contains("networkType")) {
|
||||
objectStore.deleteIndex("networkType");
|
||||
}
|
||||
if (objectStore.indexNames.contains("timestamp")) {
|
||||
objectStore.deleteIndex("timestamp");
|
||||
}
|
||||
if (objectStore.indexNames.contains("rxBytes")) {
|
||||
objectStore.deleteIndex("rxBytes");
|
||||
}
|
||||
if (objectStore.indexNames.contains("txBytes")) {
|
||||
objectStore.deleteIndex("txBytes");
|
||||
}
|
||||
if (objectStore.indexNames.contains("rxTotalBytes")) {
|
||||
objectStore.deleteIndex("rxTotalBytes");
|
||||
}
|
||||
if (objectStore.indexNames.contains("txTotalBytes")) {
|
||||
objectStore.deleteIndex("txTotalBytes");
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
debug("Deleted redundent indexes for version 4");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -935,6 +935,9 @@ function RadioInterface(options) {
|
||||
lock.get("ril.data.enabled", this);
|
||||
lock.get("ril.data.apnSettings", this);
|
||||
|
||||
// Read the default client id for data call.
|
||||
lock.get("ril.data.defaultServiceId", this);
|
||||
|
||||
// Read the "time.clock.automatic-update.enabled" setting to see if
|
||||
// we need to adjust the system clock time by NITZ or SNTP.
|
||||
lock.get(kSettingsClockAutoUpdateEnabled, this);
|
||||
@ -1742,6 +1745,34 @@ RadioInterface.prototype = {
|
||||
apnSetting.types.length);
|
||||
},
|
||||
|
||||
handleDataClientIdChange: function handleDataClientIdChange() {
|
||||
// Default data has been switched to the current RadioInterface.
|
||||
// If there is an active default data call, wait for it to get
|
||||
// disconnected, otherwise connect directly.
|
||||
if (this.clientId == this._dataDefaultClientId &&
|
||||
this._dataEnabled) {
|
||||
this.dataCallSettings.oldEnabled = this.dataCallSettings.enabled;
|
||||
this.dataCallSettings.enabled = true;
|
||||
if (gNetworkManager.active &&
|
||||
gNetworkManager.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
|
||||
if (DEBUG) this.debug("Default data active, wait for it to get disconnected.");
|
||||
this._dataCallSetupPending = true;
|
||||
return;
|
||||
}
|
||||
this.updateRILNetworkInterface();
|
||||
return;
|
||||
}
|
||||
|
||||
// Default data has been switched from this current RadioInterface,
|
||||
// disconnet data call if it is enabled.
|
||||
if (this.clientId != this._dataDefaultClientId &&
|
||||
this.dataCallSettings.enabled) {
|
||||
this.dataCallSettings.oldEnabled = this.dataCallSettings.enabled;
|
||||
this.dataCallSettings.enabled = false;
|
||||
this.updateRILNetworkInterface();
|
||||
}
|
||||
},
|
||||
|
||||
updateRILNetworkInterface: function updateRILNetworkInterface() {
|
||||
let apnSetting = this.apnSettings.byType.default;
|
||||
if (!this.validateApnSetting(apnSetting)) {
|
||||
@ -2359,6 +2390,18 @@ RadioInterface.prototype = {
|
||||
this._sntp.request();
|
||||
}
|
||||
}
|
||||
|
||||
// DSDS: setup pending data connection when switching the default id
|
||||
// for data call.
|
||||
// We can not use network.type to tell if it's NETWORK_TYPE_MOBILE,
|
||||
// since the type is removed from RILNetworkInterface.connectedTypes
|
||||
// on disconnect().
|
||||
if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN &&
|
||||
this._dataCallSetupPending) {
|
||||
if (DEBUG) this.debug("Default data disconnected, setup pending data call.");
|
||||
this._dataCallSetupPending = false;
|
||||
this.updateRILNetworkInterface();
|
||||
}
|
||||
break;
|
||||
case kScreenStateChangedTopic:
|
||||
this.workerMessenger.send("setScreenState", { on: (data === "on") });
|
||||
@ -2371,6 +2414,17 @@ RadioInterface.prototype = {
|
||||
|
||||
apnSettings: null,
|
||||
|
||||
// Flag to determine the data state to start with when we boot up. It
|
||||
// corresponds to the 'ril.data.enabled' setting from the UI.
|
||||
_dataEnabled: null,
|
||||
|
||||
// Flag to record the default client id for data call.
|
||||
_dataDefaultClientId: null,
|
||||
|
||||
// Flag to determine if we need to setup data call when we are notified
|
||||
// that another data call has been disconnected.
|
||||
_dataCallSetupPending: false,
|
||||
|
||||
// Flag to determine whether to update system clock automatically. It
|
||||
// corresponds to the "time.clock.automatic-update.enabled" setting.
|
||||
_clockAutoUpdateEnabled: null,
|
||||
@ -2430,15 +2484,15 @@ RadioInterface.prototype = {
|
||||
break;
|
||||
case "ril.data.enabled":
|
||||
if (DEBUG) this.debug("'ril.data.enabled' is now " + aResult);
|
||||
let enabled;
|
||||
if (Array.isArray(aResult)) {
|
||||
enabled = aResult[this.clientId];
|
||||
} else {
|
||||
// Backward compability
|
||||
enabled = aResult;
|
||||
if (this._dataEnabled == aResult) {
|
||||
break;
|
||||
}
|
||||
this._dataEnabled = aResult;
|
||||
if (this.clientId != this._dataDefaultClientId) {
|
||||
break;
|
||||
}
|
||||
this.dataCallSettings.oldEnabled = this.dataCallSettings.enabled;
|
||||
this.dataCallSettings.enabled = enabled;
|
||||
this.dataCallSettings.enabled = aResult;
|
||||
this.updateRILNetworkInterface();
|
||||
break;
|
||||
case "ril.data.roaming_enabled":
|
||||
@ -2453,6 +2507,15 @@ RadioInterface.prototype = {
|
||||
this.updateRILNetworkInterface();
|
||||
}
|
||||
break;
|
||||
case "ril.data.defaultServiceId":
|
||||
aResult = aResult ? aResult : 0;
|
||||
if (DEBUG) this.debug("'ril.data.defaultServiceId' is now " + aResult);
|
||||
if (this._dataDefaultClientId == aResult) {
|
||||
break;
|
||||
}
|
||||
this._dataDefaultClientId = aResult;
|
||||
this.handleDataClientIdChange();
|
||||
break;
|
||||
case kSettingsClockAutoUpdateEnabled:
|
||||
this._clockAutoUpdateEnabled = aResult;
|
||||
if (!this._clockAutoUpdateEnabled) {
|
||||
@ -3682,18 +3745,17 @@ RILNetworkInterface.prototype = {
|
||||
this.radioInterface.updateRILNetworkInterface();
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(this,
|
||||
kNetworkInterfaceStateChangedTopic,
|
||||
null);
|
||||
|
||||
if (this.state == RIL.GECKO_NETWORK_STATE_UNKNOWN &&
|
||||
this.registeredAsNetworkInterface) {
|
||||
gNetworkManager.unregisterNetworkInterface(this);
|
||||
this.registeredAsNetworkInterface = false;
|
||||
this.cid = null;
|
||||
this.connectedTypes = [];
|
||||
return;
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(this,
|
||||
kNetworkInterfaceStateChangedTopic,
|
||||
null);
|
||||
},
|
||||
|
||||
receiveDataCallList: function receiveDataCallList(dataCalls, length) {
|
||||
|
@ -94,6 +94,13 @@ partial interface HTMLElement {
|
||||
readonly attribute long offsetHeight;
|
||||
};
|
||||
|
||||
// Extension for scroll-grabbing, used in the B2G dynamic toolbar.
|
||||
// This is likely to be revised.
|
||||
partial interface HTMLElement {
|
||||
[Func="nsGenericHTMLElement::IsScrollGrabAllowed"]
|
||||
attribute boolean scrollgrab;
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface TouchEventHandlers {
|
||||
[Func="nsGenericHTMLElement::TouchEventsEnabled"]
|
||||
|
@ -42,9 +42,6 @@ interface PeerConnectionObserver
|
||||
void onAddTrack();
|
||||
void onRemoveTrack();
|
||||
|
||||
/* Used by c++ to know when Observer goes away */
|
||||
readonly attribute nsISupports weakReferent;
|
||||
|
||||
/* Helper function to access supported constraints defined in webidl. Needs to
|
||||
* be in a separate webidl object we hold, so putting it here was convenient.
|
||||
*/
|
||||
|
@ -585,6 +585,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
WriteParam(aMsg, aParam.mMayHaveTouchListeners);
|
||||
WriteParam(aMsg, aParam.mPresShellId);
|
||||
WriteParam(aMsg, aParam.mIsRoot);
|
||||
WriteParam(aMsg, aParam.mHasScrollgrab);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
@ -602,7 +603,8 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
|
||||
ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mMayHaveTouchListeners) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mIsRoot));
|
||||
ReadParam(aMsg, aIter, &aResult->mIsRoot) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasScrollgrab));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -54,6 +54,7 @@ public:
|
||||
, mMayHaveTouchListeners(false)
|
||||
, mPresShellId(-1)
|
||||
, mIsRoot(false)
|
||||
, mHasScrollgrab(false)
|
||||
{}
|
||||
|
||||
// Default copy ctor and operator= are fine
|
||||
@ -256,6 +257,9 @@ public:
|
||||
|
||||
// Whether or not this is the root scroll frame for the root content document.
|
||||
bool mIsRoot;
|
||||
|
||||
// Whether or not this frame is for an element marked 'scrollgrab'.
|
||||
bool mHasScrollgrab;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
|
||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||
|
||||
#include <algorithm> // for std::stable_sort
|
||||
|
||||
#define APZC_LOG(...)
|
||||
// #define APZC_LOG(...) printf_stderr("APZC: " __VA_ARGS__)
|
||||
|
||||
@ -271,6 +273,8 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
|
||||
mTouchCount++;
|
||||
mApzcForInputBlock = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint));
|
||||
if (multiTouchInput.mTouches.Length() == 1) // pan, not pinch
|
||||
mApzcForInputBlock = AdjustForScrollGrab(mApzcForInputBlock);
|
||||
for (size_t i = 1; i < multiTouchInput.mTouches.Length(); i++) {
|
||||
nsRefPtr<AsyncPanZoomController> apzc2 = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[i].mScreenPoint));
|
||||
mApzcForInputBlock = CommonAncestor(mApzcForInputBlock.get(), apzc2.get());
|
||||
@ -313,6 +317,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
|
||||
// then null it out so we don't keep a dangling reference and leak things.
|
||||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
mOverscrollHandoffChain.clear();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -348,6 +353,8 @@ APZCTreeManager::GetTouchInputBlockAPZC(const WidgetTouchEvent& aEvent,
|
||||
ScreenPoint aPoint)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aPoint);
|
||||
if (aEvent.touches.Length() == 1) // pan, not pinch
|
||||
apzc = AdjustForScrollGrab(apzc);
|
||||
gfx3DMatrix transformToApzc, transformToGecko;
|
||||
// Reset the cached apz transform
|
||||
mCachedTransformToApzcForInputBlock = transformToApzc;
|
||||
@ -423,6 +430,7 @@ APZCTreeManager::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
}
|
||||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
mOverscrollHandoffChain.clear();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@ -612,34 +620,37 @@ APZCTreeManager::ClearTree()
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::HandleOverscroll(AsyncPanZoomController* aChild, ScreenPoint aStartPoint, ScreenPoint aEndPoint)
|
||||
APZCTreeManager::HandleOverscroll(AsyncPanZoomController* aPrev, ScreenPoint aStartPoint, ScreenPoint aEndPoint,
|
||||
int aOverscrollHandoffChainIndex)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> parent;
|
||||
{
|
||||
// The tree lock needs to be held while navigating from an apzc to its
|
||||
// parent. We don't hold it any longer though because GetInputTransforms()
|
||||
// does its own locking, and AttemptScroll() can call HandleOverscroll()
|
||||
// recursively.
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
parent = aChild->GetParent();
|
||||
// Increment the current index into the chain of APZCs that handle overscroll
|
||||
// for the current pan gesture. Since we are in overscroll, we have scrolled
|
||||
// the previous APZC as far as possible, and will now hand off the remaining
|
||||
// scroll to the next one.
|
||||
++aOverscrollHandoffChainIndex;
|
||||
if (aOverscrollHandoffChainIndex >= mOverscrollHandoffChain.length()) {
|
||||
// Nothing more to scroll - ignore the rest of the pan gesture.
|
||||
return;
|
||||
}
|
||||
if (parent == nullptr)
|
||||
|
||||
nsRefPtr<AsyncPanZoomController> next = mOverscrollHandoffChain[aOverscrollHandoffChainIndex];
|
||||
if (next == nullptr)
|
||||
return;
|
||||
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToGecko; // ignored
|
||||
|
||||
// Convert start and end points to untransformed screen coordinates.
|
||||
GetInputTransforms(aChild, transformToApzc, transformToGecko);
|
||||
GetInputTransforms(aPrev, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc.Inverse());
|
||||
ApplyTransform(&aEndPoint, transformToApzc.Inverse());
|
||||
|
||||
// Convert start and end points to parent's transformed screen coordinates.
|
||||
GetInputTransforms(parent.get(), transformToApzc, transformToGecko);
|
||||
// Convert start and end points to next's transformed screen coordinates.
|
||||
GetInputTransforms(next, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc);
|
||||
ApplyTransform(&aEndPoint, transformToApzc);
|
||||
|
||||
parent->AttemptScroll(aStartPoint, aEndPoint);
|
||||
next->AttemptScroll(aStartPoint, aEndPoint, aOverscrollHandoffChainIndex);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -673,6 +684,13 @@ APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
struct CompareByScrollPriority
|
||||
{
|
||||
bool operator()(const nsRefPtr<AsyncPanZoomController>& a, const nsRefPtr<AsyncPanZoomController>& b) {
|
||||
return a->HasScrollgrab() && !b->HasScrollgrab();
|
||||
}
|
||||
};
|
||||
|
||||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint)
|
||||
{
|
||||
@ -689,6 +707,46 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint)
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::AdjustForScrollGrab(const nsRefPtr<AsyncPanZoomController>& aInitialTarget)
|
||||
{
|
||||
// Scroll grabbing is a mechanism that allows content to specify that
|
||||
// the initial target of a pan should be not the innermost scrollable
|
||||
// frame at the touch point (which is what GetTargetAPZC finds), but
|
||||
// something higher up in the tree.
|
||||
// It's not sufficient to just find the initial target, however, as
|
||||
// overscroll can be handed off to another APZC. Without scroll grabbing,
|
||||
// handoff just occurs from child to parent. With scroll grabbing, the
|
||||
// handoff order can be different, so we build a chain of APZCs in the
|
||||
// order in which scroll will be handed off to them.
|
||||
|
||||
mOverscrollHandoffChain.clear();
|
||||
|
||||
// Start with the child -> parent chain.
|
||||
for (AsyncPanZoomController* apzc = aInitialTarget; apzc; apzc = apzc->GetParent()) {
|
||||
if (!mOverscrollHandoffChain.append(apzc)) {
|
||||
NS_WARNING("Vector::append failed");
|
||||
mOverscrollHandoffChain.clear();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Now adjust the chain to account for scroll grabbing. Sorting is a bit
|
||||
// of an overkill here, but scroll grabbing will likely be generalized
|
||||
// to scroll priorities, so we might as well do it this way.
|
||||
// The sorting being stable ensures that the relative order between
|
||||
// non-scrollgrabbing APZCs remains child -> parent.
|
||||
// (The relative order between scrollgrabbing APZCs will also remain
|
||||
// child -> parent, though that's just an artefact of the implementation
|
||||
// and users of 'scrollgrab' should not rely on this.)
|
||||
std::stable_sort(mOverscrollHandoffChain.begin(), mOverscrollHandoffChain.end(),
|
||||
CompareByScrollPriority());
|
||||
|
||||
// The initial target is the first APZC in the handoff chain.
|
||||
nsRefPtr<AsyncPanZoomController> result = mOverscrollHandoffChain.length() > 0 ? mOverscrollHandoffChain[0] : nullptr;
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::GetRootAPZCsFor(const uint64_t& aLayersId,
|
||||
nsTArray< nsRefPtr<AsyncPanZoomController> >* aOutRootApzcs)
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "mozilla/Vector.h" // for mozilla::Vector
|
||||
|
||||
class gfx3DMatrix;
|
||||
template <class E> class nsTArray;
|
||||
@ -213,15 +214,21 @@ public:
|
||||
|
||||
/**
|
||||
* This is a callback for AsyncPanZoomController to call when a touch-move
|
||||
* event causes overscroll. The overscroll will be passed on to the parent
|
||||
* APZC. |aStartPoint| and |aEndPoint| are in |aAPZC|'s transformed screen
|
||||
* event causes overscroll. The overscroll will be passed on to the next
|
||||
* APZC in the overscroll handoff chain, which was determined in the
|
||||
* GetTargetAPZC() call for the first touch event of the touch block (usually
|
||||
* the handoff chain is child -> parent, but scroll grabbing can change this).
|
||||
* |aStartPoint| and |aEndPoint| are in |aAPZC|'s transformed screen
|
||||
* coordinates (i.e. the same coordinates in which touch points are given to
|
||||
* APZCs). The amount of the overscroll is represented by two points rather
|
||||
* than a displacement because with certain 3D transforms, the same
|
||||
* displacement between different points in transformed coordinates can
|
||||
* represent different displacements in untransformed coordinates.
|
||||
* |aOverscrollHandoffChainIndex| is |aAPZC|'s current position in the
|
||||
* overscroll handoff chain.
|
||||
*/
|
||||
void HandleOverscroll(AsyncPanZoomController* aAPZC, ScreenPoint aStartPoint, ScreenPoint aEndPoint);
|
||||
void HandleOverscroll(AsyncPanZoomController* aAPZC, ScreenPoint aStartPoint, ScreenPoint aEndPoint,
|
||||
int aOverscrollHandoffChainIndex);
|
||||
|
||||
protected:
|
||||
/**
|
||||
@ -239,6 +246,10 @@ public:
|
||||
*/
|
||||
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
|
||||
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint);
|
||||
/*
|
||||
* Adjust the target APZC of an input event to account for scroll grabbing.
|
||||
*/
|
||||
already_AddRefed<AsyncPanZoomController> AdjustForScrollGrab(const nsRefPtr<AsyncPanZoomController>& aInitialTarget);
|
||||
void GetRootAPZCsFor(const uint64_t& aLayersId,
|
||||
nsTArray< nsRefPtr<AsyncPanZoomController> >* aOutRootApzcs);
|
||||
void GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix& aTransformToApzcOut,
|
||||
@ -295,10 +306,16 @@ private:
|
||||
* screen coordinates, as returned through the 'aTransformToApzcOut' parameter
|
||||
* of GetInputTransform(), at the start of the input block. This is cached
|
||||
* because this transform can change over the course of the input block,
|
||||
* but for some operations we need to use the initial tranform.
|
||||
* but for some operations we need to use the initial transform.
|
||||
* Meaningless if mApzcForInputBlock is nullptr.
|
||||
*/
|
||||
gfx3DMatrix mCachedTransformToApzcForInputBlock;
|
||||
/* The chain of APZCs that will handle pans for the current touch input
|
||||
* block, in the order in which they will be scrolled. When one APZC has
|
||||
* been scrolled as far as it can, any overscroll will be handed off to
|
||||
* the next APZC in the chain.
|
||||
*/
|
||||
Vector< nsRefPtr<AsyncPanZoomController> > mOverscrollHandoffChain;
|
||||
|
||||
static float sDPI;
|
||||
};
|
||||
|
@ -839,7 +839,8 @@ void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput&
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
const ScreenPoint& aEndPoint) {
|
||||
const ScreenPoint& aEndPoint,
|
||||
int aOverscrollHandoffChainIndex) {
|
||||
// "start - end" rather than "end - start" because e.g. moving your finger
|
||||
// down (*positive* direction along y axis) causes the vertical scroll offset
|
||||
// to *decrease* as the page follows your finger.
|
||||
@ -878,7 +879,8 @@ void AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint,
|
||||
APZCTreeManager* treeManagerLocal = mTreeManager;
|
||||
if (treeManagerLocal) {
|
||||
// "+ overscroll" rather than "- overscroll" for the same reason as above.
|
||||
treeManagerLocal->HandleOverscroll(this, aEndPoint + overscroll, aEndPoint);
|
||||
treeManagerLocal->HandleOverscroll(this, aEndPoint + overscroll, aEndPoint,
|
||||
aOverscrollHandoffChainIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -271,8 +271,19 @@ public:
|
||||
* If this attempt causes overscroll (i.e. the layer cannot be scrolled
|
||||
* by the entire amount requested), the overscroll is passed back to the
|
||||
* tree manager via APZCTreeManager::HandleOverscroll().
|
||||
* |aOverscrollHandoffChainIndex| is used by the tree manager to keep track
|
||||
* of which APZC to hand off the overscroll to; this function simply
|
||||
* propagates it to APZCTreeManager::HandleOverscroll() in the event of
|
||||
* overscroll.
|
||||
*/
|
||||
void AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint);
|
||||
void AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint,
|
||||
int aOverscrollHandoffChainIndex = 0);
|
||||
|
||||
/**
|
||||
* Returns whether this APZC is for an element marked with the 'scrollgrab'
|
||||
* attribute.
|
||||
*/
|
||||
bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "ActiveLayerTracker.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
@ -713,6 +714,13 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
|
||||
|
||||
metrics.mPresShellId = presShell->GetPresShellId();
|
||||
|
||||
// If the scroll frame's content is marked 'scrollgrab', record this
|
||||
// in the FrameMetrics so APZ knows to provide the scroll grabbing
|
||||
// behaviour.
|
||||
if (aScrollFrame && nsContentUtils::HasScrollgrab(aScrollFrame->GetContent())) {
|
||||
metrics.mHasScrollgrab = true;
|
||||
}
|
||||
|
||||
aRoot->SetFrameMetrics(metrics);
|
||||
}
|
||||
|
||||
|
@ -2349,12 +2349,17 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
// Since making new layers is expensive, only use nsDisplayScrollLayer
|
||||
// if the area is scrollable and we're the content process.
|
||||
// if the area is scrollable and we're the content process (unless we're on
|
||||
// B2G, where we support async scrolling for scrollable elements in the
|
||||
// parent process as well).
|
||||
// When a displayport is being used, force building of a layer so that
|
||||
// CompositorParent can always find the scrollable layer for the root content
|
||||
// document.
|
||||
// If the element is marked 'scrollgrab', also force building of a layer
|
||||
// so that APZ can implement scroll grabbing.
|
||||
mShouldBuildScrollableLayer = usingDisplayport || nsContentUtils::HasScrollgrab(mOuter->GetContent());
|
||||
bool shouldBuildLayer = false;
|
||||
if (usingDisplayport) {
|
||||
if (mShouldBuildScrollableLayer) {
|
||||
shouldBuildLayer = true;
|
||||
} else {
|
||||
nsRect scrollRange = GetScrollRange();
|
||||
@ -2376,14 +2381,12 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
(!mIsRoot || !mOuter->PresContext()->IsRootContentDocument());
|
||||
}
|
||||
|
||||
mShouldBuildScrollableLayer = false;
|
||||
if (shouldBuildLayer) {
|
||||
// ScrollLayerWrapper must always be created because it initializes the
|
||||
// scroll layer count. The display lists depend on this.
|
||||
ScrollLayerWrapper wrapper(mOuter, mScrolledFrame);
|
||||
|
||||
if (usingDisplayport) {
|
||||
mShouldBuildScrollableLayer = true;
|
||||
if (mShouldBuildScrollableLayer) {
|
||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||
|
||||
// For root scrollframes in documents where the CSS viewport has been
|
||||
|
@ -677,7 +677,7 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
||||
MOZ_ASSERT(aThread);
|
||||
mThread = do_QueryInterface(aThread);
|
||||
|
||||
mPCObserver.Set(&aObserver);
|
||||
mPCObserver = do_GetWeakReference(&aObserver);
|
||||
|
||||
// Find the STS thread
|
||||
|
||||
@ -978,6 +978,28 @@ PeerConnectionImpl::CreateDataChannel(const nsAString& aLabel,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// do_QueryObjectReferent() - Helps get PeerConnectionObserver from nsWeakPtr.
|
||||
//
|
||||
// nsWeakPtr deals in XPCOM interfaces, while webidl bindings are concrete objs.
|
||||
// TODO: Turn this into a central (template) function somewhere (Bug 939178)
|
||||
//
|
||||
// Without it, each weak-ref call in this file would look like this:
|
||||
//
|
||||
// nsCOMPtr<nsISupportsWeakReference> tmp = do_QueryReferent(mPCObserver);
|
||||
// nsRefPtr<nsSupportsWeakReference> tmp2 = do_QueryObject(tmp);
|
||||
// nsRefPtr<PeerConnectionObserver> pco = static_cast<PeerConnectionObserver*>(&*tmp2);
|
||||
// if (!pco) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
static already_AddRefed<PeerConnectionObserver>
|
||||
do_QueryObjectReferent(nsIWeakReference* aRawPtr) {
|
||||
nsCOMPtr<nsISupportsWeakReference> tmp = do_QueryReferent(aRawPtr);
|
||||
nsRefPtr<nsSupportsWeakReference> tmp2 = do_QueryObject(tmp);
|
||||
nsRefPtr<PeerConnectionObserver> tmp3 = static_cast<PeerConnectionObserver*>(&*tmp2);
|
||||
return tmp3.forget();
|
||||
}
|
||||
|
||||
void
|
||||
PeerConnectionImpl::NotifyConnection()
|
||||
{
|
||||
@ -986,7 +1008,7 @@ PeerConnectionImpl::NotifyConnection()
|
||||
CSFLogDebug(logTag, "%s", __FUNCTION__);
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsRefPtr<PeerConnectionObserver> pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
@ -1007,7 +1029,7 @@ PeerConnectionImpl::NotifyClosedConnection()
|
||||
CSFLogDebug(logTag, "%s", __FUNCTION__);
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
nsRefPtr<PeerConnectionObserver> pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
@ -1047,7 +1069,7 @@ PeerConnectionImpl::NotifyDataChannel(already_AddRefed<DataChannel> aChannel)
|
||||
getter_AddRefs(domchannel));
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
nsRefPtr<PeerConnectionObserver> pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
@ -1513,7 +1535,7 @@ PeerConnectionImpl::onCallEvent(const OnCallEventArgs& args)
|
||||
break;
|
||||
}
|
||||
|
||||
nsRefPtr<PeerConnectionObserver> pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
@ -1536,7 +1558,7 @@ PeerConnectionImpl::ChangeReadyState(PCImplReadyState aReadyState)
|
||||
mReadyState = aReadyState;
|
||||
|
||||
// Note that we are passing an nsRefPtr which keeps the observer live.
|
||||
nsRefPtr<PeerConnectionObserver> pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
@ -1558,7 +1580,7 @@ PeerConnectionImpl::SetSignalingState_m(PCImplSignalingState aSignalingState)
|
||||
}
|
||||
|
||||
mSignalingState = aSignalingState;
|
||||
nsRefPtr<PeerConnectionObserver> pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return;
|
||||
}
|
||||
@ -1657,7 +1679,7 @@ PeerConnectionImpl::IceStateChange_m(PCImplIceState aState)
|
||||
break;
|
||||
}
|
||||
|
||||
nsRefPtr<PeerConnectionObserver> pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (!pco) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1760,7 +1782,7 @@ void PeerConnectionImpl::OnStatsReport_m(
|
||||
uint32_t trackId,
|
||||
nsresult result,
|
||||
nsAutoPtr<RTCStatsReportInternal> report) {
|
||||
PeerConnectionObserver* pco = mPCObserver.MayGet();
|
||||
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
|
||||
if (pco) {
|
||||
JSErrorResult rv;
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
@ -1853,30 +1875,4 @@ PeerConnectionImpl::GetRemoteStreams(nsTArray<nsRefPtr<DOMMediaStream > >& resul
|
||||
#endif
|
||||
}
|
||||
|
||||
// WeakConcretePtr gets around WeakPtr not working on concrete types by using
|
||||
// the attribute getWeakReferent, a member that supports weak refs, as a guard.
|
||||
|
||||
void
|
||||
PeerConnectionImpl::WeakConcretePtr::Set(PeerConnectionObserver *aObserver) {
|
||||
mObserver = aObserver;
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
JSErrorResult rv;
|
||||
nsCOMPtr<nsISupports> tmp = aObserver->GetWeakReferent(rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
mWeakPtr = do_GetWeakReference(tmp);
|
||||
#else
|
||||
mWeakPtr = do_GetWeakReference(aObserver);
|
||||
#endif
|
||||
}
|
||||
|
||||
PeerConnectionObserver *
|
||||
PeerConnectionImpl::WeakConcretePtr::MayGet() {
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
#endif
|
||||
nsCOMPtr<nsISupports> guard = do_QueryReferent(mWeakPtr);
|
||||
return (!guard) ? nullptr : mObserver;
|
||||
}
|
||||
|
||||
} // end sipcc namespace
|
||||
|
@ -510,20 +510,9 @@ private:
|
||||
mozilla::dom::PCImplIceState mIceState;
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
// WeakConcretePtr to PeerConnectionObserver. TODO: Remove after bug 928535
|
||||
//
|
||||
// This is only safe to use on the main thread
|
||||
// TODO: Remove if we ever properly wire PeerConnection for cycle-collection.
|
||||
class WeakConcretePtr
|
||||
{
|
||||
public:
|
||||
WeakConcretePtr() : mObserver(nullptr) {}
|
||||
void Set(PeerConnectionObserver *aObserver);
|
||||
PeerConnectionObserver *MayGet();
|
||||
private:
|
||||
PeerConnectionObserver *mObserver;
|
||||
nsWeakPtr mWeakPtr;
|
||||
} mPCObserver;
|
||||
nsWeakPtr mPCObserver;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
// The SDP sent in from JS - here for debugging.
|
||||
|
60
widget/gonk/ParentProcessController.cpp
Normal file
60
widget/gonk/ParentProcessController.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ParentProcessController.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "APZCCallbackHelper.h"
|
||||
#include "base/message_loop.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class RequestContentRepaintEvent : public nsRunnable
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
|
||||
public:
|
||||
RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics)
|
||||
: mFrameMetrics(aFrameMetrics)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(mFrameMetrics.mScrollId);
|
||||
if (content) {
|
||||
APZCCallbackHelper::UpdateSubFrame(content, mFrameMetrics);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
const FrameMetrics mFrameMetrics;
|
||||
};
|
||||
|
||||
void
|
||||
ParentProcessController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
if (aFrameMetrics.mScrollId == FrameMetrics::NULL_SCROLL_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> r = new RequestContentRepaintEvent(aFrameMetrics);
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(r);
|
||||
} else {
|
||||
r->Run();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ParentProcessController::PostDelayedTask(Task* aTask, int aDelayMs)
|
||||
{
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
34
widget/gonk/ParentProcessController.h
Normal file
34
widget/gonk/ParentProcessController.h
Normal file
@ -0,0 +1,34 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef __mozilla_widget_DynamicToolbarController_h__
|
||||
#define __mozilla_widget_DynamicToolbarController_h__
|
||||
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
class ParentProcessController : public mozilla::layers::GeckoContentController
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
|
||||
public:
|
||||
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
|
||||
virtual void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE;
|
||||
|
||||
// No-ops
|
||||
virtual void HandleDoubleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE {}
|
||||
virtual void HandleSingleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE {}
|
||||
virtual void HandleLongTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE {}
|
||||
virtual void SendAsyncScrollDOMEvent(bool aIsRoot,
|
||||
const CSSRect &aContentRect,
|
||||
const CSSSize &aScrollableSize) MOZ_OVERRIDE {}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*__mozilla_widget_DynamicToolbarController_h__ */
|
@ -54,6 +54,7 @@ SOURCES += [
|
||||
'nsWidgetFactory.cpp',
|
||||
'nsWindow.cpp',
|
||||
'OrientationObserver.cpp',
|
||||
'ParentProcessController.cpp',
|
||||
'ProcessOrientation.cpp'
|
||||
]
|
||||
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "libdisplay/GonkDisplay.h"
|
||||
#include "pixelflinger/format.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "ParentProcessController.h"
|
||||
|
||||
#include "HwcComposer2D.h"
|
||||
|
||||
@ -589,6 +591,10 @@ nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
||||
|
||||
if (sUsingOMTC) {
|
||||
CreateCompositor();
|
||||
if (mCompositorParent) {
|
||||
uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
|
||||
CompositorParent::SetControllerForLayerTree(rootLayerTreeId, new ParentProcessController());
|
||||
}
|
||||
if (mLayerManager)
|
||||
return mLayerManager;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user