michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "plstr.h" michael@0: #include "nsDeviceChannel.h" michael@0: #include "nsDeviceCaptureProvider.h" michael@0: michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: #include "mozilla/Preferences.h" michael@0: #include "AndroidCaptureProvider.h" michael@0: #endif michael@0: michael@0: using namespace mozilla; michael@0: michael@0: // Copied from image/decoders/icon/nsIconURI.cpp michael@0: // takes a string like ?size=32&contentType=text/html and returns a new string michael@0: // containing just the attribute values. i.e you could pass in this string with michael@0: // an attribute name of "size=", this will return 32 michael@0: // Assumption: attribute pairs are separated by & michael@0: void extractAttributeValue(const char* searchString, const char* attributeName, nsCString& result) michael@0: { michael@0: result.Truncate(); michael@0: michael@0: if (!searchString || !attributeName) michael@0: return; michael@0: michael@0: uint32_t attributeNameSize = strlen(attributeName); michael@0: const char *startOfAttribute = PL_strcasestr(searchString, attributeName); michael@0: if (!startOfAttribute || michael@0: !( *(startOfAttribute-1) == '?' || *(startOfAttribute-1) == '&') ) michael@0: return; michael@0: michael@0: startOfAttribute += attributeNameSize; // Skip the attributeName michael@0: if (!*startOfAttribute) michael@0: return; michael@0: michael@0: const char *endOfAttribute = strchr(startOfAttribute, '&'); michael@0: if (endOfAttribute) { michael@0: result.Assign(Substring(startOfAttribute, endOfAttribute)); michael@0: } else { michael@0: result.Assign(startOfAttribute); michael@0: } michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED(nsDeviceChannel, michael@0: nsBaseChannel, michael@0: nsIChannel) michael@0: michael@0: // nsDeviceChannel methods michael@0: nsDeviceChannel::nsDeviceChannel() michael@0: { michael@0: SetContentType(NS_LITERAL_CSTRING("image/png")); michael@0: } michael@0: michael@0: nsDeviceChannel::~nsDeviceChannel() michael@0: { michael@0: } michael@0: michael@0: nsresult michael@0: nsDeviceChannel::Init(nsIURI* aUri) michael@0: { michael@0: nsBaseChannel::Init(); michael@0: nsBaseChannel::SetURI(aUri); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsDeviceChannel::OpenContentStream(bool aAsync, michael@0: nsIInputStream** aStream, michael@0: nsIChannel** aChannel) michael@0: { michael@0: if (!aAsync) michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: michael@0: nsCOMPtr uri = nsBaseChannel::URI(); michael@0: *aStream = nullptr; michael@0: *aChannel = nullptr; michael@0: NS_NAMED_LITERAL_CSTRING(width, "width="); michael@0: NS_NAMED_LITERAL_CSTRING(height, "height="); michael@0: michael@0: nsAutoCString spec; michael@0: uri->GetSpec(spec); michael@0: michael@0: nsAutoCString type; michael@0: michael@0: nsRefPtr capture; michael@0: nsCaptureParams captureParams; michael@0: captureParams.camera = 0; michael@0: if (kNotFound != spec.Find(NS_LITERAL_CSTRING("type=image/png"), michael@0: true, michael@0: 0, michael@0: -1)) { michael@0: type.AssignLiteral("image/png"); michael@0: SetContentType(type); michael@0: captureParams.captureAudio = false; michael@0: captureParams.captureVideo = true; michael@0: captureParams.timeLimit = 0; michael@0: captureParams.frameLimit = 1; michael@0: nsAutoCString buffer; michael@0: extractAttributeValue(spec.get(), "width=", buffer); michael@0: nsresult err; michael@0: captureParams.width = buffer.ToInteger(&err); michael@0: if (!captureParams.width) michael@0: captureParams.width = 640; michael@0: extractAttributeValue(spec.get(), "height=", buffer); michael@0: captureParams.height = buffer.ToInteger(&err); michael@0: if (!captureParams.height) michael@0: captureParams.height = 480; michael@0: extractAttributeValue(spec.get(), "camera=", buffer); michael@0: captureParams.camera = buffer.ToInteger(&err); michael@0: captureParams.bpp = 32; michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: capture = GetAndroidCaptureProvider(); michael@0: #endif michael@0: } else if (kNotFound != spec.Find(NS_LITERAL_CSTRING("type=video/x-raw-yuv"), michael@0: true, michael@0: 0, michael@0: -1)) { michael@0: type.AssignLiteral("video/x-raw-yuv"); michael@0: SetContentType(type); michael@0: captureParams.captureAudio = false; michael@0: captureParams.captureVideo = true; michael@0: nsAutoCString buffer; michael@0: extractAttributeValue(spec.get(), "width=", buffer); michael@0: nsresult err; michael@0: captureParams.width = buffer.ToInteger(&err); michael@0: if (!captureParams.width) michael@0: captureParams.width = 640; michael@0: extractAttributeValue(spec.get(), "height=", buffer); michael@0: captureParams.height = buffer.ToInteger(&err); michael@0: if (!captureParams.height) michael@0: captureParams.height = 480; michael@0: extractAttributeValue(spec.get(), "camera=", buffer); michael@0: captureParams.camera = buffer.ToInteger(&err); michael@0: captureParams.bpp = 32; michael@0: captureParams.timeLimit = 0; michael@0: captureParams.frameLimit = 60000; michael@0: #ifdef MOZ_WIDGET_ANDROID michael@0: // only enable if "device.camera.enabled" is true. michael@0: if (Preferences::GetBool("device.camera.enabled", false) == true) michael@0: capture = GetAndroidCaptureProvider(); michael@0: #endif michael@0: } else { michael@0: return NS_ERROR_NOT_IMPLEMENTED; michael@0: } michael@0: michael@0: if (!capture) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: return capture->Init(type, &captureParams, aStream); michael@0: }