Merge m-c to inbound

This commit is contained in:
Wes Kocher 2014-02-20 19:37:22 -08:00
commit 07a71f7597
11 changed files with 202 additions and 89 deletions

View File

@ -90,7 +90,7 @@
<project name="platform/system/netd" path="system/netd" revision="2e226e6e636ca0a8cc4c51093e46f4baba1ffcce"/>
<project name="platform/system/vold" path="system/vold" revision="8ac5eef8ea3a456b96d52ce2091bf6d814782d8c"/>
<!-- hamachi specific things -->
<project name="quic/lf/b2g/build" path="device/qcom/b2g_common" revision="9b2d2215ee4b3413addf6222fb4ee520b2858472"/>
<project name="quic/lf/b2g/build" path="device/qcom/b2g_common" revision="43829d56fab6ad16883f1ac9f55ffb9aa5863543"/>
<project name="quic/lf/b2g/external/jsmin" path="external/jsmin" revision="cec896f0affaa0226c02605ad28d42df1bc0e393"/>
<project name="device/qcom/common" path="device/qcom/common" revision="d13aaf080177b7c48f243d51827db5c7a7873cd0"/>
<project name="platform/vendor/qcom/msm7627a" path="device/qcom/msm7627a" revision="f06bcacc6f13cec895dc5d4c2385c076396194ec"/>

View File

@ -92,6 +92,7 @@ public:
MediaEngineWebRTCVideoSource(int aIndex)
: mCameraControl(nullptr)
, mCallbackMonitor("WebRTCCamera.CallbackMonitor")
, mSensorAngle(0)
, mCaptureIndex(aIndex)
, mMonitor("WebRTCCamera.Monitor")
, mWidth(0)
@ -171,6 +172,7 @@ public:
void StartImpl(webrtc::CaptureCapability aCapability);
void StopImpl();
void SnapshotImpl();
void RotateImage(layers::Image* aImage);
#endif
// This runnable is for creating a temporary file on the main thread.
@ -205,6 +207,7 @@ private:
nsRefPtr<ICameraControl> mCameraControl;
mozilla::ReentrantMonitor mCallbackMonitor; // Monitor for camera callback handling
nsRefPtr<nsIDOMFile> mLastCapture;
int mSensorAngle;
#else
webrtc::VideoEngine* mVideoEngine; // Weak reference, don't free.
webrtc::ViEBase* mViEBase;

View File

@ -9,6 +9,10 @@
#include "nsMemory.h"
#include "mtransport/runnable_utils.h"
#ifdef MOZ_B2G_CAMERA
#include "GrallocImages.h"
#include "libyuv.h"
#endif
namespace mozilla {
using namespace mozilla::gfx;
@ -528,6 +532,8 @@ MediaEngineWebRTCVideoSource::StartImpl(webrtc::CaptureCapability aCapability) {
config.mPreviewSize.height = aCapability.height;
mCameraControl->Start(&config);
mCameraControl->Set(CAMERA_PARAM_PICTURESIZE, config.mPreviewSize);
mCameraControl->Get(CAMERA_PARAM_SENSORANGLE, mSensorAngle);
MOZ_ASSERT(mSensorAngle >= 0 && mSensorAngle < 360);
}
void
@ -580,18 +586,82 @@ MediaEngineWebRTCVideoSource::OnTakePictureComplete(uint8_t* aData, uint32_t aLe
mCallbackMonitor.Notify();
}
void
MediaEngineWebRTCVideoSource::RotateImage(layers::Image* aImage) {
layers::GrallocImage *nativeImage = static_cast<layers::GrallocImage*>(aImage);
layers::SurfaceDescriptor handle = nativeImage->GetSurfaceDescriptor();
layers::SurfaceDescriptorGralloc grallocHandle = handle.get_SurfaceDescriptorGralloc();
android::sp<android::GraphicBuffer> graphicBuffer = layers::GrallocBufferActor::GetFrom(grallocHandle);
void *pMem = nullptr;
uint32_t size = mWidth * mHeight * 3 / 2;
graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_MASK, &pMem);
uint8_t* srcPtr = static_cast<uint8_t*>(pMem);
// Create a video frame and append it to the track.
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
uint32_t dstWidth = mWidth;
uint32_t dstHeight = mHeight;
if (mSensorAngle == 90 || mSensorAngle == 270) {
dstWidth = mHeight;
dstHeight = mWidth;
}
uint32_t half_width = dstWidth / 2;
uint8_t* dstPtr = videoImage->AllocateAndGetNewBuffer(size);
libyuv::ConvertToI420(srcPtr, size,
dstPtr, dstWidth,
dstPtr + (dstWidth * dstHeight), half_width,
dstPtr + (dstWidth * dstHeight * 5 / 4), half_width,
0, 0,
mWidth, mHeight,
mWidth, mHeight,
static_cast<libyuv::RotationMode>(mSensorAngle),
libyuv::FOURCC_NV21);
graphicBuffer->unlock();
const uint8_t lumaBpp = 8;
const uint8_t chromaBpp = 4;
layers::PlanarYCbCrData data;
data.mYChannel = dstPtr;
data.mYSize = IntSize(dstWidth, dstHeight);
data.mYStride = dstWidth * lumaBpp / 8;
data.mCbCrStride = dstWidth * chromaBpp / 8;
data.mCbChannel = dstPtr + dstHeight * data.mYStride;
data.mCrChannel = data.mCbChannel +( dstHeight * data.mCbCrStride / 2);
data.mCbCrSize = IntSize(dstWidth / 2, dstHeight / 2);
data.mPicX = 0;
data.mPicY = 0;
data.mPicSize = IntSize(dstWidth, dstHeight);
data.mStereoMode = StereoMode::MONO;
videoImage->SetDataNoCopy(data);
// implicitly releases last image
mImage = image.forget();
}
bool
MediaEngineWebRTCVideoSource::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) {
MonitorAutoLock enter(mMonitor);
if (mState == kStopped) {
return false;
}
mImage = aImage;
if (mWidth != static_cast<int>(aWidth) || mHeight != static_cast<int>(aHeight)) {
mWidth = aWidth;
mHeight = aHeight;
LOG(("Video FrameSizeChange: %ux%u", mWidth, mHeight));
}
if (mSensorAngle == 0) {
mImage = aImage;
} else {
RotateImage(aImage);
}
return true; // return true because we're accepting the frame
}
#endif

View File

@ -26,6 +26,7 @@ if CONFIG['MOZ_WEBRTC']:
LOCAL_INCLUDES += [
'/dom/base',
'/dom/camera',
'/media/libyuv/include',
'/media/webrtc/signaling/src/common',
'/media/webrtc/signaling/src/common/browser_logging',
'/media/webrtc/trunk',

View File

@ -110,14 +110,14 @@ XPCOMUtils.defineLazyGetter(this, "updateSvc", function() {
});
#ifdef MOZ_WIDGET_GONK
const DIRECTORY_NAME = "webappsDir";
const DIRECTORY_KEY = "webappsDir";
#elifdef ANDROID
const DIRECTORY_NAME = "webappsDir";
const DIRECTORY_KEY = "webappsDir";
#else
// If we're executing in the context of the webapp runtime, the data files
// are in a different directory (currently the Firefox profile that installed
// the webapp); otherwise, they're in the current profile.
const DIRECTORY_NAME = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
const DIRECTORY_KEY = WEBAPP_RUNTIME ? "WebappRegD" : "ProfD";
#endif
// We'll use this to identify privileged apps that have been preinstalled
@ -161,8 +161,8 @@ this.DOMApplicationRegistry = {
AppDownloadManager.registerCancelFunction(this.cancelDownload.bind(this));
this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
["webapps", "webapps.json"], true).path;
this.appsFile = OS.Path.join(Services.dirsvc.get(DIRECTORY_KEY, Ci.nsIFile).path,
"webapps", "webapps.json");
this.loadAndUpdateApps();
},
@ -171,7 +171,10 @@ this.DOMApplicationRegistry = {
loadCurrentRegistry: function() {
return this._loadJSONAsync(this.appsFile).then((aData) => {
if (!aData) {
return;
// If _loadJSONAsync returns null, we're probably in the firstrun case
// so we may need to create the "webapps" directory.
return OS.File.makeDir(OS.Path.dirname(this.appsFile),
{ ignoreExisting: true });
}
this.webapps = aData;
@ -407,8 +410,13 @@ this.DOMApplicationRegistry = {
debug("Installing 3rd party app : " + aId +
" from " + baseDir.path);
// We copy this app to DIRECTORY_NAME/$aId, and set the base path as needed.
let destDir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
// We copy this app to DIRECTORY_KEY/$aId, and set the base path as needed.
let destDir = this._getAppDir(aId);
try {
destDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
} catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
// Ignore the exception if the directory already exists.
}
filesToMove.forEach(function(aFile) {
let file = baseDir.clone();
@ -546,44 +554,10 @@ this.DOMApplicationRegistry = {
}.bind(this)).then(null, Cu.reportError);
},
#ifdef MOZ_WIDGET_GONK
fixIndexedDb: function() {
debug("Fixing indexedDb folder names");
let idbDir = FileUtils.getDir("indexedDBPDir", ["indexedDB"]);
if (!idbDir.exists() || !idbDir.isDirectory()) {
return;
}
let re = /^(\d+)\+(.*)\+(f|t)$/;
let entries = idbDir.directoryEntries;
while (entries.hasMoreElements()) {
let entry = entries.getNext().QueryInterface(Ci.nsIFile);
if (!entry.isDirectory()) {
continue;
}
let newName = entry.leafName.replace(re, "$1+$3+$2");
if (newName != entry.leafName) {
try {
entry.moveTo(idbDir, newName);
} catch(e) { }
}
}
},
#endif
loadAndUpdateApps: function() {
return Task.spawn(function() {
let runUpdate = AppsUtils.isFirstRun(Services.prefs);
#ifdef MOZ_WIDGET_GONK
if (runUpdate) {
this.fixIndexedDb();
}
#endif
yield this.loadCurrentRegistry();
if (runUpdate) {
@ -1231,7 +1205,7 @@ this.DOMApplicationRegistry = {
},
_getAppDir: function(aId) {
return FileUtils.getDir(DIRECTORY_NAME, ["webapps", aId], true, true);
return FileUtils.getDir(DIRECTORY_KEY, ["webapps", aId], false, true);
},
_writeFile: function(aPath, aData) {
@ -1371,11 +1345,8 @@ this.DOMApplicationRegistry = {
// We need to get the update manifest here, not the webapp manifest.
// If this is an update, the update manifest is staged.
let file = FileUtils.getFile(DIRECTORY_NAME,
["webapps", id,
isUpdate ? "staged-update.webapp"
: "update.webapp"],
true);
let file = this._getAppDir(id);
file.append(isUpdate ? "staged-update.webapp" : "update.webapp");
if (!file.exists()) {
// This is a hosted app, let's check if it has an appcache
@ -1465,13 +1436,13 @@ this.DOMApplicationRegistry = {
// We need to get the old manifest to unregister web activities.
this.getManifestFor(aManifestURL).then((aOldManifest) => {
// Move the application.zip and manifest.webapp files out of TmpD
let tmpDir = FileUtils.getDir("TmpD", ["webapps", id], true, true);
let tmpDir = FileUtils.getDir("TmpD", ["webapps", id], false, true);
let manFile = tmpDir.clone();
manFile.append("manifest.webapp");
let appFile = tmpDir.clone();
appFile.append("application.zip");
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id], true, true);
let dir = this._getAppDir(id);
appFile.moveTo(dir, "application.zip");
manFile.moveTo(dir, "manifest.webapp");
@ -2234,16 +2205,14 @@ this.DOMApplicationRegistry = {
},
denyInstall: function(aData) {
let packageId = aData.app.packageId;
if (packageId) {
let dir = FileUtils.getDir("TmpD", ["webapps", packageId],
true, true);
try {
dir.remove(true);
} catch(e) {
Task.spawn(function*() {
let packageId = aData.app.packageId;
if (packageId) {
let dir = OS.Path.join(OS.Constants.Path.tmpDir, "webapps", packageId);
yield OS.File.removeDir(dir, { ignoreAbsent: true });
}
}
aData.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
aData.mm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
}).then(null, Cu.reportError);
},
// This function is called after we called the onsuccess callback on the
@ -2345,14 +2314,13 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
return appObject;
},
_writeManifestFile: function(aId, aIsPackage, aJsonManifest) {
_writeManifestFile: function(aDir, aIsPackage, aJsonManifest) {
debug("_writeManifestFile");
// For packaged apps, keep the update manifest distinct from the app manifest.
let manifestName = aIsPackage ? "update.webapp" : "manifest.webapp";
let dir = this._getAppDir(aId).path;
let manFile = OS.Path.join(dir, manifestName);
let manFile = OS.Path.join(aDir, manifestName);
this._writeFile(manFile, JSON.stringify(aJsonManifest));
},
@ -2378,10 +2346,18 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
localId = this._nextLocalId();
}
// Create the app directory
let dir = this._getAppDir(id);
try {
dir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
} catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
// Ignore the exception if the directory already exists.
}
let app = this._setupApp(aData, id);
let jsonManifest = aData.isPackage ? app.updateManifest : app.manifest;
this._writeManifestFile(id, aData.isPackage, jsonManifest);
this._writeManifestFile(dir.path, aData.isPackage, jsonManifest);
debug("app.origin: " + app.origin);
let manifest = new ManifestHelper(jsonManifest, app.origin);
@ -2501,11 +2477,14 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
debug("_onDownloadPackage");
// Success! Move the zip out of TmpD.
let app = this.webapps[aId];
let zipFile =
FileUtils.getFile("TmpD", ["webapps", aId, "application.zip"], true);
let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], false, true);
let zipFile = tmpDir.clone();
zipFile.append("application.zip");
let dir = this._getAppDir(aId);
zipFile.moveTo(dir, "application.zip");
let tmpDir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
try {
tmpDir.remove(true);
} catch(e) { }
@ -2598,7 +2577,7 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
if (!this._manifestCache[id]) {
// the manifest file used to be named manifest.json, so fallback on this.
let baseDir = this.webapps[id].basePath == this.getCoreAppsBasePath()
? "coreAppsDir" : DIRECTORY_NAME;
? "coreAppsDir" : DIRECTORY_KEY;
let dir = FileUtils.getDir(baseDir, ["webapps", id], false, true);
@ -2726,7 +2705,7 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
debug("No deviceStorage");
// deviceStorage isn't available, so use FileUtils to find the size of
// available storage.
let dir = FileUtils.getDir(DIRECTORY_NAME, ["webapps"], true, true);
let dir = FileUtils.getDir(DIRECTORY_KEY, ["webapps"], false, true);
try {
let sufficientStorage = this._checkDownloadSize(dir.diskSpaceAvailable,
aNewApp);
@ -2983,10 +2962,9 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
eventType: ["downloadsuccess", "downloadapplied"]
});
});
let file = FileUtils.getFile("TmpD", ["webapps", aId], false);
if (file && file.exists()) {
file.remove(true);
}
let appDir = OS.Path.join(OS.Constants.Path.tmpDir, "webapps", aId);
OS.File.removeDir(appDir, { ignoreAbsent: true });
},
_openAndReadPackage: function(aZipFile, aOldApp, aNewApp, aIsLocalFileInstall,
@ -3251,9 +3229,9 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
this.webapps[newId] = aOldApp;
delete this.webapps[oldId];
// Rename the directories where the files are installed.
[DIRECTORY_NAME, "TmpD"].forEach(function(aDir) {
let parent = FileUtils.getDir(aDir, ["webapps"], true, true);
let dir = FileUtils.getDir(aDir, ["webapps", oldId], true, true);
[DIRECTORY_KEY, "TmpD"].forEach(function(aDir) {
let parent = FileUtils.getDir(aDir, ["webapps"], false, true);
let dir = FileUtils.getDir(aDir, ["webapps", oldId], false, true);
dir.moveTo(parent, newId);
});
// Signals that we need to swap the old id with the new app.
@ -3330,7 +3308,7 @@ onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
// Removes the directory we created, and sends an error to the DOM side.
_revertDownloadPackage: function(aId, aOldApp, aNewApp, aIsUpdate, aError) {
debug("Cleanup: " + aError + "\n" + aError.stack);
let dir = FileUtils.getDir("TmpD", ["webapps", aId], true, true);
let dir = FileUtils.getDir("TmpD", ["webapps", aId], false, true);
try {
dir.remove(true);
} catch (e) { }

View File

@ -160,7 +160,9 @@ RPWatchContext.prototype = {
},
doError: function RPWatchContext_onerror(aMessage) {
log("doError: " + aMessage);
log("doError: " + this.id + ": " + aMessage);
let message = new IDDOMMessage({id: this.id, message: aMessage});
this._mm.sendAsyncMessage("Identity:RP:Watch:OnError", message);
}
};

View File

@ -480,6 +480,16 @@ nsDOMIdentity.prototype = {
this._onCancelRequestCallback();
}
break;
case "Identity:RP:Watch:OnError":
if (!this._rpWatcher) {
this._log("WARNING: Received OnError message, but there is no RP watcher");
return;
}
if (this._rpWatcher.onerror) {
this._rpWatcher.onerror(msg.message);
}
break;
case "Identity:IDP:CallBeginProvisioningCallback":
this._callBeginProvisioningCallback(msg);
break;
@ -651,6 +661,7 @@ nsDOMIdentityInternal.prototype = {
"Identity:RP:Watch:OnLogout",
"Identity:RP:Watch:OnReady",
"Identity:RP:Watch:OnCancel",
"Identity:RP:Watch:OnError",
"Identity:IDP:CallBeginProvisioningCallback",
"Identity:IDP:CallGenKeyPairCallback",
"Identity:IDP:CallBeginAuthenticationCallback"

View File

@ -275,6 +275,12 @@ WebappsActor.prototype = {
// Move manifest.webapp to the destination directory.
// The destination directory for this app.
let installDir = DOMApplicationRegistry._getAppDir(aId);
try {
installDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
} catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
// Ignore the exception if the directory already exists.
}
if (aManifest) {
let manFile = OS.Path.join(installDir.path, "manifest.webapp");
return DOMApplicationRegistry._writeFile(manFile, JSON.stringify(aManifest)).then(() => {
@ -394,6 +400,12 @@ WebappsActor.prototype = {
// we can move application.zip to the destination directory, and
// extract manifest.webapp there.
let installDir = DOMApplicationRegistry._getAppDir(id);
try {
installDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
} catch (ex if ex.result == Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
// Ignore the exception if the directory already exists.
}
let manFile = installDir.clone();
manFile.append("manifest.webapp");
zipReader.extract("manifest.webapp", manFile);

View File

@ -133,6 +133,7 @@ FxAccountsService.prototype = {
},
error => {
log.error("get assertion failed: " + JSON.stringify(error));
this.doError(aRPId, error);
}
);
},

View File

@ -26,7 +26,7 @@ MockFXAManager.prototype = {
let originalManager = FirefoxAccounts.fxAccountsManager;
FirefoxAccounts.fxAccountsManager = new MockFXAManager();
do_register_cleanup(() => {
print("restoring fxaccountsmanager");
log("restoring fxaccountsmanager");
FirefoxAccounts.fxAccountsManager = originalManager;
});
@ -111,6 +111,48 @@ function test_logout() {
FirefoxAccounts.RP.watch(mockedRP);
}
function test_error() {
do_test_pending();
let received = [];
// Mock the fxAccountsManager so that getAssertion rejects its promise and
// triggers our onerror handler. (This is the method that's used internally
// by FirefoxAccounts.RP.request().)
let originalManager = FirefoxAccounts.fxAccountsManager;
FirefoxAccounts.RP.fxAccountsManager = {
getAssertion: function(audience) {
return Promise.reject("barf!");
}
};
let mockedRP = mock_fxa_rp(null, TEST_URL, function(method, message) {
// We will receive "ready" as a result of watch(), and "logout"
// as a result of logout()
received.push([method, message]);
if (received.length == 2) {
do_check_eq(received[0][0], "ready");
do_check_eq(received[1][0], "error");
do_check_eq(received[1][1], "barf!");
// Put things back the way they were
FirefoxAccounts.fxAccountsManager = originalManager;
do_test_finished();
run_next_test();
}
if (method == "ready") {
FirefoxAccounts.RP.request(mockedRP.id);
}
});
// First, call watch()
FirefoxAccounts.RP.watch(mockedRP);
}
function test_child_process_shutdown() {
do_test_pending();
let rpCount = FirefoxAccounts.RP._rpFlows.size;
@ -158,6 +200,7 @@ let TESTS = [
test_watch,
test_request,
test_logout,
test_error,
test_child_process_shutdown,
];

View File

@ -81,14 +81,6 @@ function createBrandingFiles() {
// It waits for XUL window and webapps registry loading.
this.startup = function(window) {
return Task.spawn(function () {
// Observe registry loading.
let deferredRegistry = Promise.defer();
function observeRegistryLoading() {
Services.obs.removeObserver(observeRegistryLoading, "webapps-registry-start");
deferredRegistry.resolve();
}
Services.obs.addObserver(observeRegistryLoading, "webapps-registry-start", false);
// Observe XUL window loading.
// For tests, it could be already loaded.
let deferredWindowLoad = Promise.defer();
@ -102,7 +94,7 @@ this.startup = function(window) {
}
// Wait for webapps registry loading.
yield deferredRegistry.promise;
yield DOMApplicationRegistry.registryStarted;
// Install/update permissions and get the appID from the webapps registry.
let appID = Ci.nsIScriptSecurityManager.NO_APP_ID;