From 7960e1d75c20801e184a5a6c7ddfb6e4badb6ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabrice=20Desr=C3=A9?= Date: Mon, 6 Feb 2012 22:48:50 -0800 Subject: [PATCH] Bug 708484 - Add camera capture stream provider for gonk (temporary solution) - get camera working in webpages [r=bz] --- b2g/app/b2g.js | 4 + b2g/chrome/content/shell.js | 3 +- b2g/components/B2GComponents.manifest | 5 + b2g/components/CameraContent.js | 83 +++++++++++++ b2g/components/Makefile.in | 5 + b2g/components/b2g.idl | 12 ++ b2g/installer/package-manifest.in | 1 + netwerk/build/nsNetCID.h | 11 ++ netwerk/build/nsNetModule.cpp | 13 ++ netwerk/protocol/device/Makefile.in | 1 + .../protocol/device/nsB2GProtocolHandler.cpp | 117 ++++++++++++++++++ .../protocol/device/nsB2GProtocolHandler.h | 60 +++++++++ 12 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 b2g/components/CameraContent.js create mode 100644 b2g/components/b2g.idl create mode 100644 netwerk/protocol/device/nsB2GProtocolHandler.cpp create mode 100644 netwerk/protocol/device/nsB2GProtocolHandler.h diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index 5bd5a4055a4..08bd3d12720 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -413,6 +413,10 @@ pref("dom.sms.whitelist", "file://,http://localhost:6666"); // Ignore X-Frame-Options headers. pref("b2g.ignoreXFrameOptions", true); +// controls if we want camera support +pref("device.camera.enabled", true); +pref("media.realtime_decoder.enabled", true); + // "Preview" landing of bug 710563, which is bogged down in analysis // of talos regression. This is a needed change for higher-framerate // CSS animations, and incidentally works around an apparent bug in diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index c11cd0dacf2..9e003616b03 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -79,9 +79,10 @@ function startupHttpd(baseDir, port) { // FIXME Bug 707625 // until we have a proper security model, add some rights to // the pre-installed web applications +// XXX never grant 'content-camera' to non-gaia apps function addPermissions(urls) { let permissions = [ - 'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app' + 'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'content-camera' ]; urls.forEach(function(url) { let uri = Services.io.newURI(url, null, null); diff --git a/b2g/components/B2GComponents.manifest b/b2g/components/B2GComponents.manifest index 2d6ef29cf56..81accf98538 100644 --- a/b2g/components/B2GComponents.manifest +++ b/b2g/components/B2GComponents.manifest @@ -1,2 +1,7 @@ # Scrollbars category agent-style-sheets browser-content-stylesheet chrome://browser/content/content.css + +# CameraContent.js +component {eff4231b-abce-4f7f-a40a-d646e8fde3ce} CameraContent.js +contract @mozilla.org/b2g-camera-content;1 {eff4231b-abce-4f7f-a40a-d646e8fde3ce} +category JavaScript-navigator-property mozCamera @mozilla.org/b2g-camera-content;1 diff --git a/b2g/components/CameraContent.js b/b2g/components/CameraContent.js new file mode 100644 index 00000000000..65ad85a70af --- /dev/null +++ b/b2g/components/CameraContent.js @@ -0,0 +1,83 @@ +/* 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/. */ + +"use strict"; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +const kProtocolName = "b2g-camera:"; + +let CameraContent = function() { + this.hasPrivileges = false; + this.mapping = []; +} + +CameraContent.prototype = { + getCameraURI: function(aOptions) { + if (!this.hasPrivileges) + return null; + + let options = aOptions || { }; + if (!options.camera) + options.camera = 0; + if (!options.width) + options.width = 320; + if (!options.height) + options.height = 240; + + let uuid = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID().toString(); + uuid = uuid.substring(1, uuid.length - 2); // remove the brackets + this.mapping.push(uuid); + let uri = kProtocolName + "?camera=" + options.camera + + "&width=" + options.width + + "&height=" + options.height + + "&type=video/x-raw-yuv"; + // XXX that's no e10s ready, but the camera inputstream itself is not... + Services.prefs.setCharPref("b2g.camera." + kProtocolName + "?" + uuid, uri); + return kProtocolName + "?" + uuid; + }, + + observe: function(aSubject, aTopic, aData) { + if (aTopic == "inner-window-destroyed") { + let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data; + if (wId == this.innerWindowID) { + Services.obs.removeObserver(this, "inner-window-destroyed"); + for (let aId in this.mapping) + Services.prefs.clearUserPref("b2g.camera." + kProtocolName + "?" + aId); + this.mapping = null; + } + } + }, + + init: function(aWindow) { + let principal = aWindow.document.nodePrincipal; + let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager); + + let perm = principal == secMan.getSystemPrincipal() ? Ci.nsIPermissionManager.ALLOW_ACTION : Services.perms.testExactPermission(principal.URI, "content-camera"); + + //only pages with perm set and chrome pages can use the camera in content + this.hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION || from.schemeIs("chrome"); + + Services.obs.addObserver(this, "inner-window-destroyed", false); + let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); + this.innerWindowID = util.currentInnerWindowID; + }, + + classID: Components.ID("{eff4231b-abce-4f7f-a40a-d646e8fde3ce}"), + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIB2GCameraContent, Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIObserver]), + + classInfo: XPCOMUtils.generateCI({classID: Components.ID("{eff4231b-abce-4f7f-a40a-d646e8fde3ce}"), + contractID: "@mozilla.org/b2g-camera-content;1", + interfaces: [Ci.nsIB2GCameraContent], + flags: Ci.nsIClassInfo.DOM_OBJECT, + classDescription: "B2G Camera Content Helper"}) +} + +const NSGetFactory = XPCOMUtils.generateNSGetFactory([CameraContent]); diff --git a/b2g/components/Makefile.in b/b2g/components/Makefile.in index a837f027699..d6420a178a5 100644 --- a/b2g/components/Makefile.in +++ b/b2g/components/Makefile.in @@ -44,8 +44,13 @@ include $(DEPTH)/config/autoconf.mk MODULE = B2GComponents XPIDL_MODULE = B2GComponents +XPIDLSRCS = \ + b2g.idl \ + $(NULL) + EXTRA_PP_COMPONENTS = \ B2GComponents.manifest \ + CameraContent.js \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/b2g/components/b2g.idl b/b2g/components/b2g.idl new file mode 100644 index 00000000000..fe45af18c42 --- /dev/null +++ b/b2g/components/b2g.idl @@ -0,0 +1,12 @@ +/* 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 "domstubs.idl" + +[scriptable, uuid(3615a616-571d-4194-bf54-ccf546067b14)] +interface nsIB2GCameraContent : nsISupports +{ + /* temporary solution, waiting for getUserMedia */ + DOMString getCameraURI([optional] in jsval options); +}; diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 999baaedaa8..ff427492356 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -603,3 +603,4 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@ @BINPATH@/chrome/chrome.manifest @BINPATH@/components/B2GComponents.manifest @BINPATH@/components/B2GComponents.xpt +@BINPATH@/components/CameraContent.js diff --git a/netwerk/build/nsNetCID.h b/netwerk/build/nsNetCID.h index 56650d96c15..4413b91c82b 100644 --- a/netwerk/build/nsNetCID.h +++ b/netwerk/build/nsNetCID.h @@ -709,6 +709,17 @@ {0xae, 0xb7, 0xda, 0x62, 0xe7, 0x27, 0x3e, 0xd5} \ } +#ifdef MOZ_WIDGET_GONK +#define NS_B2GPROTOCOLHANDLER_CLASSNAME \ + "nsB2GProtocolHandler" +#define NS_B2GPROTOCOLHANDLER_CID \ +{ \ +/* {e50d101a-9db2-466f-977c-ae6af19e3b2f} */ \ + 0x50d101a, 0x9db2, 0x466f, \ + {0x97, 0x7c, 0xae, 0x6a, 0xf1, 0x9e, 0x3b, 0x2f} \ +} +#endif + /****************************************************************************** * netwerk/protocol/viewsource/ classes */ diff --git a/netwerk/build/nsNetModule.cpp b/netwerk/build/nsNetModule.cpp index 5b7b9cefe46..d7aadc0788c 100644 --- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -264,6 +264,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsResURL) #ifdef NECKO_PROTOCOL_device #include "nsDeviceProtocolHandler.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceProtocolHandler) +#ifdef MOZ_WIDGET_GONK +#include "nsB2GProtocolHandler.h" +NS_GENERIC_FACTORY_CONSTRUCTOR(nsB2GProtocolHandler) +#endif #endif #ifdef NECKO_PROTOCOL_viewsource @@ -779,6 +783,9 @@ NS_DEFINE_NAMED_CID(NS_DATAPROTOCOLHANDLER_CID); #endif #ifdef NECKO_PROTOCOL_device NS_DEFINE_NAMED_CID(NS_DEVICEPROTOCOLHANDLER_CID); +#ifdef MOZ_WIDGET_GONK +NS_DEFINE_NAMED_CID(NS_B2GPROTOCOLHANDLER_CID); +#endif #endif #ifdef NECKO_PROTOCOL_viewsource NS_DEFINE_NAMED_CID(NS_VIEWSOURCEHANDLER_CID); @@ -910,6 +917,9 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = { #endif #ifdef NECKO_PROTOCOL_device { &kNS_DEVICEPROTOCOLHANDLER_CID, false, NULL, nsDeviceProtocolHandlerConstructor}, +#ifdef MOZ_WIDGET_GONK + { &kNS_B2GPROTOCOLHANDLER_CID, false, NULL, nsB2GProtocolHandlerConstructor}, +#endif #endif #ifdef NECKO_PROTOCOL_viewsource { &kNS_VIEWSOURCEHANDLER_CID, false, NULL, nsViewSourceHandlerConstructor }, @@ -1050,6 +1060,9 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = { #endif #ifdef NECKO_PROTOCOL_device { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "moz-device", &kNS_DEVICEPROTOCOLHANDLER_CID }, +#ifdef MOZ_WIDGET_GONK + { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "b2g-camera", &kNS_B2GPROTOCOLHANDLER_CID }, +#endif #endif #ifdef NECKO_PROTOCOL_viewsource { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "view-source", &kNS_VIEWSOURCEHANDLER_CID }, diff --git a/netwerk/protocol/device/Makefile.in b/netwerk/protocol/device/Makefile.in index a0a71252547..78634c4b223 100644 --- a/netwerk/protocol/device/Makefile.in +++ b/netwerk/protocol/device/Makefile.in @@ -66,6 +66,7 @@ endif ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) CPPSRCS += GonkCaptureProvider.cpp \ + nsB2GProtocolHandler.cpp \ $(NULL) endif diff --git a/netwerk/protocol/device/nsB2GProtocolHandler.cpp b/netwerk/protocol/device/nsB2GProtocolHandler.cpp new file mode 100644 index 00000000000..4aaa8b89249 --- /dev/null +++ b/netwerk/protocol/device/nsB2GProtocolHandler.cpp @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Camera. + * + * The Initial Developer of the Original Code is Mozilla Corporation + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Nino D'Aversa + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsB2GProtocolHandler.h" +#include "nsDeviceChannel.h" +#include "nsNetCID.h" +#include "nsAutoPtr.h" +#include "nsCOMPtr.h" +#include "nsSimpleURI.h" +#include "mozilla/Preferences.h" +//----------------------------------------------------------------------------- + +NS_IMPL_THREADSAFE_ISUPPORTS1(nsB2GProtocolHandler, + nsIProtocolHandler) + +nsresult +nsB2GProtocolHandler::Init(){ + return NS_OK; +} + +NS_IMETHODIMP +nsB2GProtocolHandler::GetScheme(nsACString &aResult) +{ + aResult.AssignLiteral("b2g-camera"); + return NS_OK; +} + +NS_IMETHODIMP +nsB2GProtocolHandler::GetDefaultPort(PRInt32 *aResult) +{ + *aResult = -1; // no port for b2g-camera: URLs + return NS_OK; +} + +NS_IMETHODIMP +nsB2GProtocolHandler::GetProtocolFlags(PRUint32 *aResult) +{ + *aResult = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE | URI_IS_LOCAL_RESOURCE; + return NS_OK; +} + +NS_IMETHODIMP +nsB2GProtocolHandler::NewURI(const nsACString &spec, + const char *originCharset, + nsIURI *baseURI, + nsIURI **result) +{ + nsRefPtr uri = new nsSimpleURI(); + nsresult rv; + + // XXX get the "real" uri from the pref + // should use ipdl when we'll use e10s + nsCString key("b2g.camera."); + key.Append(spec); + nsCString pref; + rv = mozilla::Preferences::GetCString(key.get(), &pref); + NS_ENSURE_SUCCESS(rv, rv); + rv = uri->SetSpec(pref); + mozilla::Preferences::ClearUser(key.BeginReading()); + NS_ENSURE_SUCCESS(rv, rv); + + return CallQueryInterface(uri, result); +} + +NS_IMETHODIMP +nsB2GProtocolHandler::NewChannel(nsIURI* aURI, nsIChannel **aResult) +{ + nsRefPtr channel = new nsDeviceChannel(); + nsresult rv = channel->Init(aURI); + NS_ENSURE_SUCCESS(rv, rv); + + return CallQueryInterface(channel, aResult); +} + +NS_IMETHODIMP +nsB2GProtocolHandler::AllowPort(PRInt32 port, + const char *scheme, + bool *aResult) +{ + // don't override anything. + *aResult = false; + return NS_OK; +} diff --git a/netwerk/protocol/device/nsB2GProtocolHandler.h b/netwerk/protocol/device/nsB2GProtocolHandler.h new file mode 100644 index 00000000000..171ade8f936 --- /dev/null +++ b/netwerk/protocol/device/nsB2GProtocolHandler.h @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Camera. + * + * The Initial Developer of the Original Code is Mozilla Corporation + * Portions created by the Initial Developer are Copyright (C) 2009 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Nino D'Aversa + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsB2GProtocolHandler_h_ +#define nsB2GProtocolHandler_h_ + +#include "nsIProtocolHandler.h" +#include "nsString.h" + +// {e50d101a-9db2-466f-977c-ae6af19e3b2f} +#define NS_B2GPROTOCOLHANDLER_CID \ +{ 0x50d101a, 0x9db2, 0x466f, \ + {0x97, 0x7c, 0xae, 0x6a, 0xf1, 0x9e, 0x3b, 0x2f} } + +class nsB2GProtocolHandler : public nsIProtocolHandler { +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPROTOCOLHANDLER + + nsB2GProtocolHandler() {} + ~nsB2GProtocolHandler() {} + + nsresult Init(); +}; + +#endif