Adds --disable-npapi as an additional build option. The default is still to build in NPAPI compatibility, but with this flag, it's finally possible to build without pulling in GTK2 on systems that don't have the package. This essentially ifdefs everything associated with NPAPI, following various Mozilla removal bugs. Ref: BZ 1682030, BZ 1251202, BZ 1217665, BZ 1687239
1512 lines
39 KiB
C++
1512 lines
39 KiB
C++
/* -*- Mode: C++; tab-width: 8; 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/. */
|
|
|
|
// Needs to be first.
|
|
#include "base/basictypes.h"
|
|
|
|
#include "Navigator.h"
|
|
#include "nsIXULAppInfo.h"
|
|
#ifdef MOZ_ENABLE_NPAPI
|
|
#include "nsPluginArray.h"
|
|
#endif
|
|
#include "nsMimeTypeArray.h"
|
|
#include "mozilla/MemoryReporting.h"
|
|
#include "mozilla/dom/BodyExtractor.h"
|
|
#include "mozilla/dom/DesktopNotification.h"
|
|
#include "mozilla/dom/FetchBinding.h"
|
|
#include "mozilla/dom/File.h"
|
|
#include "nsGeolocation.h"
|
|
#include "nsIClassOfService.h"
|
|
#include "nsIHttpProtocolHandler.h"
|
|
#include "nsIContentPolicy.h"
|
|
#include "nsIContentSecurityPolicy.h"
|
|
#include "nsContentPolicyUtils.h"
|
|
#include "nsISupportsPriority.h"
|
|
#include "nsICachingChannel.h"
|
|
#include "nsIWebContentHandlerRegistrar.h"
|
|
#include "nsICookiePermission.h"
|
|
#include "nsIScriptSecurityManager.h"
|
|
#include "nsCharSeparatedTokenizer.h"
|
|
#include "nsContentUtils.h"
|
|
#include "nsUnicharUtils.h"
|
|
#include "mozilla/Preferences.h"
|
|
#include "mozilla/dom/Clipboard.h"
|
|
#ifdef MOZ_GAMEPAD
|
|
#include "mozilla/dom/GamepadServiceTest.h"
|
|
#endif
|
|
#include "mozilla/dom/PowerManager.h"
|
|
#include "mozilla/dom/WakeLock.h"
|
|
#include "mozilla/dom/power/PowerManagerService.h"
|
|
#include "mozilla/dom/Permissions.h"
|
|
#include "mozilla/dom/ServiceWorkerContainer.h"
|
|
#include "mozilla/dom/StorageManager.h"
|
|
#include "mozilla/dom/TCPSocket.h"
|
|
#include "mozilla/dom/URLSearchParams.h"
|
|
#include "mozilla/dom/workers/RuntimeService.h"
|
|
#include "mozilla/Hal.h"
|
|
#include "nsISiteSpecificUserAgent.h"
|
|
#include "mozilla/ClearOnShutdown.h"
|
|
#include "mozilla/SSE.h"
|
|
#include "mozilla/StaticPtr.h"
|
|
#include "Connection.h"
|
|
#include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
|
|
#include "nsGlobalWindow.h"
|
|
#include "nsIIdleObserver.h"
|
|
#include "nsIPermissionManager.h"
|
|
#include "nsMimeTypes.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsStringStream.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsIStringStream.h"
|
|
#include "nsIHttpChannel.h"
|
|
#include "nsIHttpChannelInternal.h"
|
|
#include "TimeManager.h"
|
|
#include "nsStreamUtils.h"
|
|
#include "nsIAppsService.h"
|
|
#include "mozIApplication.h"
|
|
#include "WidgetUtils.h"
|
|
#include "mozilla/dom/MediaDevices.h"
|
|
#include "MediaManager.h"
|
|
|
|
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
|
|
#include "AudioChannelManager.h"
|
|
#endif
|
|
|
|
#include "nsIDOMGlobalPropertyInitializer.h"
|
|
#include "nsJSUtils.h"
|
|
|
|
#include "nsScriptNameSpaceManager.h"
|
|
|
|
#include "mozilla/dom/NavigatorBinding.h"
|
|
#include "mozilla/dom/Promise.h"
|
|
|
|
#include "nsIUploadChannel2.h"
|
|
#include "mozilla/dom/FormData.h"
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "WorkerPrivate.h"
|
|
#include "WorkerRunnable.h"
|
|
|
|
#if defined(XP_LINUX)
|
|
#include "mozilla/Hal.h"
|
|
#endif
|
|
#include "mozilla/dom/ContentChild.h"
|
|
|
|
namespace mozilla {
|
|
namespace dom {
|
|
|
|
static void
|
|
AddPermission(nsIPrincipal* aPrincipal, const char* aType, uint32_t aPermission,
|
|
uint32_t aExpireType, int64_t aExpireTime)
|
|
{
|
|
MOZ_ASSERT(aType);
|
|
MOZ_ASSERT(aPrincipal);
|
|
|
|
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
|
if (!permMgr) {
|
|
return;
|
|
}
|
|
permMgr->AddFromPrincipal(aPrincipal, aType, aPermission, aExpireType,
|
|
aExpireTime);
|
|
}
|
|
|
|
static uint32_t
|
|
GetPermission(nsPIDOMWindowInner* aWindow, const char* aType)
|
|
{
|
|
MOZ_ASSERT(aType);
|
|
|
|
uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
|
|
|
|
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
|
if (!permMgr) {
|
|
return permission;
|
|
}
|
|
permMgr->TestPermissionFromWindow(aWindow, aType, &permission);
|
|
return permission;
|
|
}
|
|
|
|
static uint32_t
|
|
GetPermission(nsIPrincipal* aPrincipal, const char* aType)
|
|
{
|
|
MOZ_ASSERT(aType);
|
|
MOZ_ASSERT(aPrincipal);
|
|
|
|
uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
|
|
|
|
nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
|
|
if (!permMgr) {
|
|
return permission;
|
|
}
|
|
permMgr->TestPermissionFromPrincipal(aPrincipal, aType, &permission);
|
|
return permission;
|
|
}
|
|
|
|
/* static */
|
|
void
|
|
Navigator::Init()
|
|
{
|
|
// Add any Preferences::Add*VarCache(&sPref, "pref", default) here if needed.
|
|
}
|
|
|
|
Navigator::Navigator(nsPIDOMWindowInner* aWindow)
|
|
: mWindow(aWindow)
|
|
{
|
|
MOZ_ASSERT(aWindow->IsInnerWindow(), "Navigator must get an inner window!");
|
|
}
|
|
|
|
Navigator::~Navigator()
|
|
{
|
|
Invalidate();
|
|
}
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Navigator)
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNavigator)
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator)
|
|
NS_INTERFACE_MAP_ENTRY(nsIMozNavigatorNetwork)
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(Navigator)
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(Navigator)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(Navigator)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Navigator)
|
|
tmp->Invalidate();
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes)
|
|
#ifdef MOZ_ENABLE_NPAPI
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
|
|
#endif
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
|
|
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelManager)
|
|
#endif
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaDevices)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimeManager)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
|
#ifdef MOZ_GAMEPAD
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest)
|
|
#endif
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVRGetDisplaysPromises)
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(Navigator)
|
|
|
|
void
|
|
Navigator::Invalidate()
|
|
{
|
|
// Don't clear mWindow here so we know we've got a non-null mWindow
|
|
// until we're unlinked.
|
|
|
|
mMimeTypes = nullptr;
|
|
|
|
#ifdef MOZ_ENABLE_NPAPI
|
|
if (mPlugins) {
|
|
mPlugins->Invalidate();
|
|
mPlugins = nullptr;
|
|
}
|
|
#endif
|
|
|
|
mPermissions = nullptr;
|
|
|
|
mStorageManager = nullptr;
|
|
|
|
// If there is a page transition, make sure delete the geolocation object.
|
|
if (mGeolocation) {
|
|
mGeolocation->Shutdown();
|
|
mGeolocation = nullptr;
|
|
}
|
|
|
|
if (mNotification) {
|
|
mNotification->Shutdown();
|
|
mNotification = nullptr;
|
|
}
|
|
|
|
if (mPowerManager) {
|
|
mPowerManager->Shutdown();
|
|
mPowerManager = nullptr;
|
|
}
|
|
|
|
if (mConnection) {
|
|
mConnection->Shutdown();
|
|
mConnection = nullptr;
|
|
}
|
|
|
|
mMediaDevices = nullptr;
|
|
|
|
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
|
|
if (mAudioChannelManager) {
|
|
mAudioChannelManager = nullptr;
|
|
}
|
|
#endif
|
|
|
|
if (mTimeManager) {
|
|
mTimeManager = nullptr;
|
|
}
|
|
|
|
mServiceWorkerContainer = nullptr;
|
|
|
|
#ifdef MOZ_GAMEPAD
|
|
if (mGamepadServiceTest) {
|
|
mGamepadServiceTest->Shutdown();
|
|
mGamepadServiceTest = nullptr;
|
|
}
|
|
#endif
|
|
|
|
mVRGetDisplaysPromises.Clear();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Navigator::nsIDOMNavigator
|
|
//*****************************************************************************
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetUserAgent(nsAString& aUserAgent)
|
|
{
|
|
nsCOMPtr<nsIURI> codebaseURI;
|
|
nsCOMPtr<nsPIDOMWindowInner> window;
|
|
|
|
if (mWindow) {
|
|
window = mWindow;
|
|
nsIDocShell* docshell = window->GetDocShell();
|
|
nsString customUserAgent;
|
|
if (docshell) {
|
|
docshell->GetCustomUserAgent(customUserAgent);
|
|
|
|
if (!customUserAgent.IsEmpty()) {
|
|
aUserAgent = customUserAgent;
|
|
return NS_OK;
|
|
}
|
|
|
|
nsIDocument* doc = mWindow->GetExtantDoc();
|
|
if (doc) {
|
|
doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
|
|
}
|
|
}
|
|
}
|
|
|
|
return GetUserAgent(window, codebaseURI, nsContentUtils::IsCallerChrome(),
|
|
aUserAgent);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetAppCodeName(nsAString& aAppCodeName)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIHttpProtocolHandler>
|
|
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString appName;
|
|
rv = service->GetAppName(appName);
|
|
CopyASCIItoUTF16(appName, aAppCodeName);
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetAppVersion(nsAString& aAppVersion)
|
|
{
|
|
return GetAppVersion(aAppVersion, /* aUsePrefOverriddenValue */ true);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetAppName(nsAString& aAppName)
|
|
{
|
|
AppName(aAppName, /* aUsePrefOverriddenValue */ true);
|
|
return NS_OK;
|
|
}
|
|
|
|
/**
|
|
* Returns the value of Accept-Languages (HTTP header) as a nsTArray of
|
|
* languages. The value is set in the preference by the user ("Content
|
|
* Languages").
|
|
*
|
|
* "en", "en-US" and "i-cherokee" and "" are valid languages tokens.
|
|
*
|
|
* An empty array will be returned if there is no valid languages.
|
|
*/
|
|
/* static */ void
|
|
Navigator::GetAcceptLanguages(nsTArray<nsString>& aLanguages)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
aLanguages.Clear();
|
|
|
|
// E.g. "de-de, en-us,en".
|
|
const nsAdoptingString& acceptLang =
|
|
Preferences::GetLocalizedString("intl.accept_languages");
|
|
|
|
// Split values on commas.
|
|
nsCharSeparatedTokenizer langTokenizer(acceptLang, ',');
|
|
while (langTokenizer.hasMoreTokens()) {
|
|
nsDependentSubstring lang = langTokenizer.nextToken();
|
|
|
|
// Replace "_" with "-" to avoid POSIX/Windows "en_US" notation.
|
|
// NOTE: we should probably rely on the pref being set correctly.
|
|
if (lang.Length() > 2 && lang[2] == char16_t('_')) {
|
|
lang.Replace(2, 1, char16_t('-'));
|
|
}
|
|
|
|
// Use uppercase for country part, e.g. "en-US", not "en-us", see BCP47
|
|
// only uppercase 2-letter country codes, not "zh-Hant", "de-DE-x-goethe".
|
|
// NOTE: we should probably rely on the pref being set correctly.
|
|
if (lang.Length() > 2) {
|
|
nsCharSeparatedTokenizer localeTokenizer(lang, '-');
|
|
int32_t pos = 0;
|
|
bool first = true;
|
|
while (localeTokenizer.hasMoreTokens()) {
|
|
const nsSubstring& code = localeTokenizer.nextToken();
|
|
|
|
if (code.Length() == 2 && !first) {
|
|
nsAutoString upper(code);
|
|
ToUpperCase(upper);
|
|
lang.Replace(pos, code.Length(), upper);
|
|
}
|
|
|
|
pos += code.Length() + 1; // 1 is the separator
|
|
first = false;
|
|
}
|
|
}
|
|
|
|
aLanguages.AppendElement(lang);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Do not use UI language (chosen app locale) here but the first value set in
|
|
* the Accept Languages header, see ::GetAcceptLanguages().
|
|
*
|
|
* See RFC 2616, Section 15.1.4 "Privacy Issues Connected to Accept Headers" for
|
|
* the reasons why.
|
|
*/
|
|
NS_IMETHODIMP
|
|
Navigator::GetLanguage(nsAString& aLanguage)
|
|
{
|
|
nsTArray<nsString> languages;
|
|
GetLanguages(languages);
|
|
if (languages.Length() >= 1) {
|
|
aLanguage.Assign(languages[0]);
|
|
} else {
|
|
aLanguage.Truncate();
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
void
|
|
Navigator::GetLanguages(nsTArray<nsString>& aLanguages)
|
|
{
|
|
GetAcceptLanguages(aLanguages);
|
|
|
|
// The returned value is cached by the binding code. The window listen to the
|
|
// accept languages change and will clear the cache when needed. It has to
|
|
// take care of dispatching the DOM event already and the invalidation and the
|
|
// event has to be timed correctly.
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetPlatform(nsAString& aPlatform)
|
|
{
|
|
return GetPlatform(aPlatform, /* aUsePrefOverriddenValue */ true);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetOscpu(nsAString& aOSCPU)
|
|
{
|
|
if (!nsContentUtils::IsCallerChrome()) {
|
|
const nsAdoptingString& override =
|
|
Preferences::GetString("general.oscpu.override");
|
|
|
|
if (override) {
|
|
aOSCPU = override;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIHttpProtocolHandler>
|
|
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString oscpu;
|
|
rv = service->GetOscpu(oscpu);
|
|
CopyASCIItoUTF16(oscpu, aOSCPU);
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetVendor(nsAString& aVendor)
|
|
{
|
|
aVendor.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetVendorSub(nsAString& aVendorSub)
|
|
{
|
|
aVendorSub.Truncate();
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetProduct(nsAString& aProduct)
|
|
{
|
|
aProduct.AssignLiteral("Gecko");
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetProductSub(nsAString& aProductSub)
|
|
{
|
|
// Legacy build ID hardcoded for backward compatibility (bug 776376)
|
|
aProductSub.AssignLiteral("20100101");
|
|
return NS_OK;
|
|
}
|
|
|
|
nsMimeTypeArray*
|
|
Navigator::GetMimeTypes(ErrorResult& aRv)
|
|
{
|
|
if (!mMimeTypes) {
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
mMimeTypes = new nsMimeTypeArray(mWindow);
|
|
}
|
|
|
|
return mMimeTypes;
|
|
}
|
|
|
|
#ifdef MOZ_ENABLE_NPAPI
|
|
nsPluginArray*
|
|
Navigator::GetPlugins(ErrorResult& aRv)
|
|
{
|
|
if (!mPlugins) {
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
mPlugins = new nsPluginArray(mWindow);
|
|
mPlugins->Init();
|
|
}
|
|
|
|
return mPlugins;
|
|
}
|
|
#endif
|
|
|
|
Permissions*
|
|
Navigator::GetPermissions(ErrorResult& aRv)
|
|
{
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
|
|
if (!mPermissions) {
|
|
mPermissions = new Permissions(mWindow);
|
|
}
|
|
|
|
return mPermissions;
|
|
}
|
|
|
|
StorageManager*
|
|
Navigator::Storage()
|
|
{
|
|
MOZ_ASSERT(mWindow);
|
|
|
|
if(!mStorageManager) {
|
|
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
|
|
MOZ_ASSERT(global);
|
|
|
|
mStorageManager = new StorageManager(global);
|
|
}
|
|
|
|
return mStorageManager;
|
|
}
|
|
|
|
// Values for the network.cookie.cookieBehavior pref are documented in
|
|
// nsCookieService.cpp.
|
|
#define COOKIE_BEHAVIOR_REJECT 2
|
|
|
|
bool
|
|
Navigator::CookieEnabled()
|
|
{
|
|
bool cookieEnabled =
|
|
(Preferences::GetInt("network.cookie.cookieBehavior",
|
|
COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT);
|
|
|
|
// Check whether an exception overrides the global cookie behavior
|
|
// Note that the code for getting the URI here matches that in
|
|
// nsHTMLDocument::SetCookie.
|
|
if (!mWindow || !mWindow->GetDocShell()) {
|
|
return cookieEnabled;
|
|
}
|
|
|
|
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
|
if (!doc) {
|
|
return cookieEnabled;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> codebaseURI;
|
|
doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
|
|
|
|
if (!codebaseURI) {
|
|
// Not a codebase, so technically can't set cookies, but let's
|
|
// just return the default value.
|
|
return cookieEnabled;
|
|
}
|
|
|
|
nsCOMPtr<nsICookiePermission> permMgr =
|
|
do_GetService(NS_COOKIEPERMISSION_CONTRACTID);
|
|
NS_ENSURE_TRUE(permMgr, cookieEnabled);
|
|
|
|
// Pass null for the channel, just like the cookie service does.
|
|
nsCookieAccess access;
|
|
nsresult rv = permMgr->CanAccess(codebaseURI, nullptr, &access);
|
|
NS_ENSURE_SUCCESS(rv, cookieEnabled);
|
|
|
|
if (access != nsICookiePermission::ACCESS_DEFAULT) {
|
|
cookieEnabled = access != nsICookiePermission::ACCESS_DENY;
|
|
}
|
|
|
|
return cookieEnabled;
|
|
}
|
|
|
|
bool
|
|
Navigator::OnLine()
|
|
{
|
|
return !NS_IsOffline();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetBuildID(nsAString& aBuildID)
|
|
{
|
|
if (!nsContentUtils::IsCallerChrome()) {
|
|
const nsAdoptingString& override =
|
|
Preferences::GetString("general.buildID.override");
|
|
|
|
if (override) {
|
|
aBuildID = override;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
nsCOMPtr<nsIXULAppInfo> appInfo =
|
|
do_GetService("@mozilla.org/xre/app-info;1");
|
|
if (!appInfo) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
nsAutoCString buildID;
|
|
nsresult rv = appInfo->GetAppBuildID(buildID);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
aBuildID.Truncate();
|
|
AppendASCIItoUTF16(buildID, aBuildID);
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
Navigator::GlobalPrivacyControl()
|
|
{
|
|
return nsContentUtils::GPCEnabled();
|
|
}
|
|
|
|
bool
|
|
Navigator::JavaEnabled(ErrorResult& aRv)
|
|
{
|
|
// Return true if we have a handler for the java mime
|
|
nsAdoptingString javaMIME = Preferences::GetString("plugin.java.mime");
|
|
NS_ENSURE_TRUE(!javaMIME.IsEmpty(), false);
|
|
|
|
if (!mMimeTypes) {
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return false;
|
|
}
|
|
mMimeTypes = new nsMimeTypeArray(mWindow);
|
|
}
|
|
|
|
RefreshMIMEArray();
|
|
|
|
nsMimeType *mimeType = mMimeTypes->NamedItem(javaMIME);
|
|
|
|
return mimeType && mimeType->GetEnabledPlugin();
|
|
}
|
|
|
|
uint64_t
|
|
Navigator::HardwareConcurrency()
|
|
{
|
|
workers::RuntimeService* rts = workers::RuntimeService::GetOrCreateService();
|
|
if (!rts) {
|
|
return 1;
|
|
}
|
|
|
|
return rts->ClampedHardwareConcurrency();
|
|
}
|
|
|
|
bool
|
|
Navigator::CpuHasSSE2()
|
|
{
|
|
return mozilla::supports_sse2();
|
|
}
|
|
|
|
void
|
|
Navigator::RefreshMIMEArray()
|
|
{
|
|
if (mMimeTypes) {
|
|
mMimeTypes->Refresh();
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
|
{
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return;
|
|
}
|
|
CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
|
|
nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
|
|
if (NS_FAILED(mWindow->RegisterIdleObserver(obs))) {
|
|
NS_WARNING("Failed to add idle observer.");
|
|
}
|
|
}
|
|
|
|
void
|
|
Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
|
{
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return;
|
|
}
|
|
CallbackObjectHolder<MozIdleObserver, nsIIdleObserver> holder(&aIdleObserver);
|
|
nsCOMPtr<nsIIdleObserver> obs = holder.ToXPCOMCallback();
|
|
if (NS_FAILED(mWindow->UnregisterIdleObserver(obs))) {
|
|
NS_WARNING("Failed to remove idle observer.");
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Pointer Events interface
|
|
//*****************************************************************************
|
|
|
|
uint32_t
|
|
Navigator::MaxTouchPoints()
|
|
{
|
|
nsCOMPtr<nsIWidget> widget = widget::WidgetUtils::DOMWindowToWidget(mWindow->GetOuterWindow());
|
|
|
|
NS_ENSURE_TRUE(widget, 0);
|
|
return widget->GetMaxTouchPoints();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
// Navigator::nsIDOMClientInformation
|
|
//*****************************************************************************
|
|
|
|
void
|
|
Navigator::RegisterContentHandler(const nsAString& aMIMEType,
|
|
const nsAString& aURI,
|
|
const nsAString& aTitle,
|
|
ErrorResult& aRv)
|
|
{
|
|
if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
|
|
do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
|
|
if (!registrar) {
|
|
return;
|
|
}
|
|
|
|
aRv = registrar->RegisterContentHandler(aMIMEType, aURI, aTitle,
|
|
mWindow->GetOuterWindow());
|
|
}
|
|
|
|
void
|
|
Navigator::RegisterProtocolHandler(const nsAString& aProtocol,
|
|
const nsAString& aURI,
|
|
const nsAString& aTitle,
|
|
ErrorResult& aRv)
|
|
{
|
|
if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
|
|
return;
|
|
}
|
|
|
|
nsCOMPtr<nsIWebContentHandlerRegistrar> registrar =
|
|
do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID);
|
|
if (!registrar) {
|
|
return;
|
|
}
|
|
|
|
aRv = registrar->RegisterProtocolHandler(aProtocol, aURI, aTitle,
|
|
mWindow->GetOuterWindow());
|
|
}
|
|
|
|
Geolocation*
|
|
Navigator::GetGeolocation(ErrorResult& aRv)
|
|
{
|
|
if (mGeolocation) {
|
|
return mGeolocation;
|
|
}
|
|
|
|
if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) {
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
return nullptr;
|
|
}
|
|
|
|
mGeolocation = new Geolocation();
|
|
if (NS_FAILED(mGeolocation->Init(mWindow))) {
|
|
mGeolocation = nullptr;
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
return nullptr;
|
|
}
|
|
|
|
return mGeolocation;
|
|
}
|
|
|
|
class BeaconStreamListener final : public nsIStreamListener
|
|
{
|
|
~BeaconStreamListener() {}
|
|
|
|
public:
|
|
BeaconStreamListener() : mLoadGroup(nullptr) {}
|
|
|
|
void SetLoadGroup(nsILoadGroup* aLoadGroup) {
|
|
mLoadGroup = aLoadGroup;
|
|
}
|
|
|
|
NS_DECL_ISUPPORTS
|
|
NS_DECL_NSISTREAMLISTENER
|
|
NS_DECL_NSIREQUESTOBSERVER
|
|
|
|
private:
|
|
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
|
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS(BeaconStreamListener,
|
|
nsIStreamListener,
|
|
nsIRequestObserver)
|
|
|
|
NS_IMETHODIMP
|
|
BeaconStreamListener::OnStartRequest(nsIRequest *aRequest,
|
|
nsISupports *aContext)
|
|
{
|
|
// release the loadgroup first
|
|
mLoadGroup = nullptr;
|
|
|
|
aRequest->Cancel(NS_ERROR_NET_INTERRUPT);
|
|
return NS_BINDING_ABORTED;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BeaconStreamListener::OnStopRequest(nsIRequest *aRequest,
|
|
nsISupports *aContext,
|
|
nsresult aStatus)
|
|
{
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
BeaconStreamListener::OnDataAvailable(nsIRequest *aRequest,
|
|
nsISupports *ctxt,
|
|
nsIInputStream *inStr,
|
|
uint64_t sourceOffset,
|
|
uint32_t count)
|
|
{
|
|
MOZ_ASSERT(false);
|
|
return NS_OK;
|
|
}
|
|
|
|
bool
|
|
Navigator::SendBeacon(const nsAString& aUrl,
|
|
const Nullable<fetch::BodyInit>& aData,
|
|
ErrorResult& aRv)
|
|
{
|
|
if (aData.IsNull()) {
|
|
return SendBeaconInternal(aUrl, nullptr, eBeaconTypeOther, aRv);
|
|
}
|
|
|
|
if (aData.Value().IsArrayBuffer()) {
|
|
BodyExtractor<const ArrayBuffer> body(&aData.Value().GetAsArrayBuffer());
|
|
return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
|
|
}
|
|
|
|
if (aData.Value().IsArrayBufferView()) {
|
|
BodyExtractor<const ArrayBufferView> body(&aData.Value().GetAsArrayBufferView());
|
|
return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
|
|
}
|
|
|
|
if (aData.Value().IsBlob()) {
|
|
BodyExtractor<nsIXHRSendable> body(&aData.Value().GetAsBlob());
|
|
return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
|
|
}
|
|
|
|
if (aData.Value().IsFormData()) {
|
|
BodyExtractor<nsIXHRSendable> body(&aData.Value().GetAsFormData());
|
|
return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
|
|
}
|
|
|
|
if (aData.Value().IsUSVString()) {
|
|
BodyExtractor<const nsAString> body(&aData.Value().GetAsUSVString());
|
|
return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
|
|
}
|
|
|
|
if (aData.Value().IsURLSearchParams()) {
|
|
BodyExtractor<nsIXHRSendable> body(&aData.Value().GetAsURLSearchParams());
|
|
return SendBeaconInternal(aUrl, &body, eBeaconTypeOther, aRv);
|
|
}
|
|
|
|
MOZ_CRASH("Invalid data type.");
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
Navigator::SendBeaconInternal(const nsAString& aUrl,
|
|
BodyExtractorBase* aBody,
|
|
BeaconType aType,
|
|
ErrorResult& aRv)
|
|
{
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIDocument> doc = mWindow->GetDoc();
|
|
if (!doc) {
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
return false;
|
|
}
|
|
|
|
nsIURI* documentURI = doc->GetDocumentURI();
|
|
if (!documentURI) {
|
|
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
|
nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
|
|
getter_AddRefs(uri),
|
|
aUrl,
|
|
doc,
|
|
doc->GetDocBaseURI());
|
|
if (NS_FAILED(rv)) {
|
|
aRv.ThrowTypeError<MSG_INVALID_URL>(aUrl);
|
|
return false;
|
|
}
|
|
|
|
// Spec disallows any schemes save for HTTP/HTTPs
|
|
bool isValidScheme;
|
|
if (!(NS_SUCCEEDED(uri->SchemeIs("http", &isValidScheme)) && isValidScheme) &&
|
|
!(NS_SUCCEEDED(uri->SchemeIs("https", &isValidScheme)) && isValidScheme)) {
|
|
aRv.ThrowTypeError<MSG_INVALID_URL_SCHEME>( NS_LITERAL_STRING("Beacon"), aUrl);
|
|
return false;
|
|
}
|
|
|
|
nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL;
|
|
|
|
// No need to use CORS for sendBeacon unless it's a BLOB
|
|
nsSecurityFlags securityFlags = aType == eBeaconTypeBlob
|
|
? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS
|
|
: nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
|
|
securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
|
|
|
|
nsCOMPtr<nsIChannel> channel;
|
|
rv = NS_NewChannel(getter_AddRefs(channel),
|
|
uri,
|
|
doc,
|
|
securityFlags,
|
|
nsIContentPolicy::TYPE_BEACON,
|
|
nullptr, // aLoadGroup
|
|
nullptr, // aCallbacks
|
|
loadFlags);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
aRv.Throw(rv);
|
|
return false;
|
|
}
|
|
|
|
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
|
if (!httpChannel) {
|
|
// Beacon spec only supports HTTP requests at this time
|
|
aRv.Throw(NS_ERROR_DOM_BAD_URI);
|
|
return false;
|
|
}
|
|
httpChannel->SetReferrer(documentURI);
|
|
|
|
nsCOMPtr<nsIInputStream> in;
|
|
nsAutoCString contentTypeWithCharset;
|
|
nsAutoCString charset;
|
|
uint64_t length = 0;
|
|
|
|
if (aBody) {
|
|
aRv = aBody->GetAsStream(getter_AddRefs(in), &length,
|
|
contentTypeWithCharset, charset);
|
|
if (NS_WARN_IF(aRv.Failed())) {
|
|
return false;
|
|
}
|
|
|
|
if (aType == eBeaconTypeArrayBuffer) {
|
|
MOZ_ASSERT(contentTypeWithCharset.IsEmpty());
|
|
MOZ_ASSERT(charset.IsEmpty());
|
|
contentTypeWithCharset.Assign("application/octet-stream");
|
|
}
|
|
|
|
nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(channel);
|
|
if (!uploadChannel) {
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
return false;
|
|
}
|
|
uploadChannel->ExplicitSetUploadStream(in, contentTypeWithCharset, length,
|
|
NS_LITERAL_CSTRING("POST"),
|
|
false);
|
|
} else {
|
|
httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
|
|
}
|
|
|
|
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(channel);
|
|
if (p) {
|
|
p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
|
|
}
|
|
|
|
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
|
|
if (cos) {
|
|
cos->AddClassFlags(nsIClassOfService::Background);
|
|
}
|
|
|
|
// The channel needs to have a loadgroup associated with it, so that we can
|
|
// cancel the channel and any redirected channels it may create.
|
|
nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
|
|
nsCOMPtr<nsIInterfaceRequestor> callbacks =
|
|
do_QueryInterface(mWindow->GetDocShell());
|
|
loadGroup->SetNotificationCallbacks(callbacks);
|
|
channel->SetLoadGroup(loadGroup);
|
|
|
|
RefPtr<BeaconStreamListener> beaconListener = new BeaconStreamListener();
|
|
rv = channel->AsyncOpen2(beaconListener);
|
|
// do not throw if security checks fail within asyncOpen2
|
|
NS_ENSURE_SUCCESS(rv, false);
|
|
|
|
// make the beaconListener hold a strong reference to the loadgroup
|
|
// which is released in ::OnStartRequest
|
|
beaconListener->SetLoadGroup(loadGroup);
|
|
|
|
return true;
|
|
}
|
|
|
|
MediaDevices*
|
|
Navigator::GetMediaDevices(ErrorResult& aRv)
|
|
{
|
|
if (!mMediaDevices) {
|
|
if (!mWindow ||
|
|
!mWindow->GetOuterWindow() ||
|
|
mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
|
|
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
|
return nullptr;
|
|
}
|
|
mMediaDevices = new MediaDevices(mWindow);
|
|
}
|
|
return mMediaDevices;
|
|
}
|
|
|
|
void
|
|
Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
|
|
NavigatorUserMediaSuccessCallback& aOnSuccess,
|
|
NavigatorUserMediaErrorCallback& aOnError,
|
|
ErrorResult& aRv)
|
|
{
|
|
CallbackObjectHolder<NavigatorUserMediaSuccessCallback,
|
|
nsIDOMGetUserMediaSuccessCallback> holder1(&aOnSuccess);
|
|
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onsuccess =
|
|
holder1.ToXPCOMCallback();
|
|
|
|
CallbackObjectHolder<NavigatorUserMediaErrorCallback,
|
|
nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
|
|
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
|
|
|
|
if (!mWindow || !mWindow->GetOuterWindow() ||
|
|
mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
|
|
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
|
return;
|
|
}
|
|
|
|
MediaManager* manager = MediaManager::Get();
|
|
aRv = manager->GetUserMedia(mWindow, aConstraints, onsuccess, onerror);
|
|
}
|
|
|
|
void
|
|
Navigator::MozGetUserMediaDevices(const MediaStreamConstraints& aConstraints,
|
|
MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
|
|
NavigatorUserMediaErrorCallback& aOnError,
|
|
uint64_t aInnerWindowID,
|
|
const nsAString& aCallID,
|
|
ErrorResult& aRv)
|
|
{
|
|
CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback,
|
|
nsIGetUserMediaDevicesSuccessCallback> holder1(&aOnSuccess);
|
|
nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onsuccess =
|
|
holder1.ToXPCOMCallback();
|
|
|
|
CallbackObjectHolder<NavigatorUserMediaErrorCallback,
|
|
nsIDOMGetUserMediaErrorCallback> holder2(&aOnError);
|
|
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onerror = holder2.ToXPCOMCallback();
|
|
|
|
if (!mWindow || !mWindow->GetOuterWindow() ||
|
|
mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
|
|
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
|
return;
|
|
}
|
|
|
|
MediaManager* manager = MediaManager::Get();
|
|
aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
|
|
aInnerWindowID, aCallID);
|
|
}
|
|
|
|
DesktopNotificationCenter*
|
|
Navigator::GetMozNotification(ErrorResult& aRv)
|
|
{
|
|
if (mNotification) {
|
|
return mNotification;
|
|
}
|
|
|
|
if (!mWindow || !mWindow->GetDocShell()) {
|
|
aRv.Throw(NS_ERROR_FAILURE);
|
|
return nullptr;
|
|
}
|
|
|
|
mNotification = new DesktopNotificationCenter(mWindow);
|
|
return mNotification;
|
|
}
|
|
|
|
PowerManager*
|
|
Navigator::GetMozPower(ErrorResult& aRv)
|
|
{
|
|
if (!mPowerManager) {
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
mPowerManager = PowerManager::CreateInstance(mWindow);
|
|
if (!mPowerManager) {
|
|
// We failed to get the power manager service?
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
}
|
|
}
|
|
|
|
return mPowerManager;
|
|
}
|
|
|
|
already_AddRefed<WakeLock>
|
|
Navigator::RequestWakeLock(const nsAString &aTopic, ErrorResult& aRv)
|
|
{
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
|
|
RefPtr<power::PowerManagerService> pmService =
|
|
power::PowerManagerService::GetInstance();
|
|
// Maybe it went away for some reason... Or maybe we're just called
|
|
// from our XPCOM method.
|
|
if (!pmService) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
|
|
return pmService->NewWakeLock(aTopic, mWindow, aRv);
|
|
}
|
|
|
|
already_AddRefed<LegacyMozTCPSocket>
|
|
Navigator::MozTCPSocket()
|
|
{
|
|
RefPtr<LegacyMozTCPSocket> socket = new LegacyMozTCPSocket(GetWindow());
|
|
return socket.forget();
|
|
}
|
|
|
|
#ifdef MOZ_GAMEPAD
|
|
void
|
|
Navigator::GetGamepads(nsTArray<RefPtr<Gamepad> >& aGamepads,
|
|
ErrorResult& aRv)
|
|
{
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return;
|
|
}
|
|
NS_ENSURE_TRUE_VOID(mWindow->GetDocShell());
|
|
nsGlobalWindow* win = nsGlobalWindow::Cast(mWindow);
|
|
win->SetHasGamepadEventListener(true);
|
|
win->GetGamepads(aGamepads);
|
|
}
|
|
|
|
GamepadServiceTest*
|
|
Navigator::RequestGamepadServiceTest()
|
|
{
|
|
if (!mGamepadServiceTest) {
|
|
mGamepadServiceTest = GamepadServiceTest::CreateTestService(mWindow);
|
|
}
|
|
return mGamepadServiceTest;
|
|
}
|
|
#endif
|
|
|
|
//*****************************************************************************
|
|
// Navigator::nsIMozNavigatorNetwork
|
|
//*****************************************************************************
|
|
|
|
NS_IMETHODIMP
|
|
Navigator::GetProperties(nsINetworkProperties** aProperties)
|
|
{
|
|
ErrorResult rv;
|
|
NS_IF_ADDREF(*aProperties = GetConnection(rv));
|
|
return NS_OK;
|
|
}
|
|
|
|
network::Connection*
|
|
Navigator::GetConnection(ErrorResult& aRv)
|
|
{
|
|
if (!mConnection) {
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
mConnection = new network::Connection(mWindow);
|
|
}
|
|
|
|
return mConnection;
|
|
}
|
|
|
|
#ifdef MOZ_TIME_MANAGER
|
|
time::TimeManager*
|
|
Navigator::GetMozTime(ErrorResult& aRv)
|
|
{
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
|
|
if (!mTimeManager) {
|
|
mTimeManager = new time::TimeManager(mWindow);
|
|
}
|
|
|
|
return mTimeManager;
|
|
}
|
|
#endif
|
|
|
|
already_AddRefed<ServiceWorkerContainer>
|
|
Navigator::ServiceWorker()
|
|
{
|
|
MOZ_ASSERT(mWindow);
|
|
|
|
if (!mServiceWorkerContainer) {
|
|
mServiceWorkerContainer = new ServiceWorkerContainer(mWindow);
|
|
}
|
|
|
|
RefPtr<ServiceWorkerContainer> ref = mServiceWorkerContainer;
|
|
return ref.forget();
|
|
}
|
|
|
|
size_t
|
|
Navigator::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|
{
|
|
size_t n = aMallocSizeOf(this);
|
|
|
|
// TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
|
|
// TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114.
|
|
// TODO: add SizeOfIncludingThis() to Geolocation, bug 674115.
|
|
// TODO: add SizeOfIncludingThis() to DesktopNotificationCenter, bug 674116.
|
|
|
|
return n;
|
|
}
|
|
|
|
void
|
|
Navigator::SetWindow(nsPIDOMWindowInner *aInnerWindow)
|
|
{
|
|
NS_ASSERTION(aInnerWindow->IsInnerWindow(),
|
|
"Navigator must get an inner window!");
|
|
mWindow = aInnerWindow;
|
|
}
|
|
|
|
void
|
|
Navigator::OnNavigation()
|
|
{
|
|
if (!mWindow) {
|
|
return;
|
|
}
|
|
|
|
// If MediaManager is open let it inform any live streams or pending callbacks
|
|
MediaManager *manager = MediaManager::GetIfExists();
|
|
if (manager) {
|
|
manager->OnNavigation(mWindow->WindowID());
|
|
}
|
|
}
|
|
|
|
bool
|
|
Navigator::CheckPermission(const char* type)
|
|
{
|
|
return CheckPermission(mWindow, type);
|
|
}
|
|
|
|
/* static */
|
|
bool
|
|
Navigator::CheckPermission(nsPIDOMWindowInner* aWindow, const char* aType)
|
|
{
|
|
if (!aWindow) {
|
|
return false;
|
|
}
|
|
|
|
uint32_t permission = GetPermission(aWindow, aType);
|
|
return permission == nsIPermissionManager::ALLOW_ACTION;
|
|
}
|
|
|
|
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
|
|
system::AudioChannelManager*
|
|
Navigator::GetMozAudioChannelManager(ErrorResult& aRv)
|
|
{
|
|
if (!mAudioChannelManager) {
|
|
if (!mWindow) {
|
|
aRv.Throw(NS_ERROR_UNEXPECTED);
|
|
return nullptr;
|
|
}
|
|
mAudioChannelManager = new system::AudioChannelManager();
|
|
mAudioChannelManager->Init(mWindow);
|
|
}
|
|
|
|
return mAudioChannelManager;
|
|
}
|
|
#endif
|
|
|
|
JSObject*
|
|
Navigator::WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto)
|
|
{
|
|
return NavigatorBinding::Wrap(cx, this, aGivenProto);
|
|
}
|
|
|
|
/* static */
|
|
bool
|
|
Navigator::HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */)
|
|
{
|
|
nsCOMPtr<nsIPowerManagerService> pmService =
|
|
do_GetService(POWERMANAGERSERVICE_CONTRACTID);
|
|
// No service means no wake lock support
|
|
return !!pmService;
|
|
}
|
|
|
|
/* static */
|
|
bool
|
|
Navigator::HasWifiManagerSupport(JSContext* /* unused */,
|
|
JSObject* aGlobal)
|
|
{
|
|
// On XBL scope, the global object is NOT |window|. So we have
|
|
// to use nsContentUtils::GetObjectPrincipal to get the principal
|
|
// and test directly with permission manager.
|
|
|
|
nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aGlobal);
|
|
uint32_t permission = GetPermission(principal, "wifi-manage");
|
|
|
|
return permission == nsIPermissionManager::ALLOW_ACTION;
|
|
}
|
|
|
|
/* static */
|
|
bool
|
|
Navigator::HasUserMediaSupport(JSContext* /* unused */,
|
|
JSObject* /* unused */)
|
|
{
|
|
// Make enabling peerconnection enable getUserMedia() as well
|
|
return Preferences::GetBool("media.navigator.enabled", false) ||
|
|
Preferences::GetBool("media.peerconnection.enabled", false);
|
|
}
|
|
|
|
/* static */
|
|
bool
|
|
Navigator::IsE10sEnabled(JSContext* aCx, JSObject* aGlobal)
|
|
{
|
|
// We no longer support this, so always false.
|
|
// TODO: Remove this.
|
|
return false;
|
|
}
|
|
|
|
/* static */
|
|
already_AddRefed<nsPIDOMWindowInner>
|
|
Navigator::GetWindowFromGlobal(JSObject* aGlobal)
|
|
{
|
|
nsCOMPtr<nsPIDOMWindowInner> win =
|
|
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
|
|
MOZ_ASSERT(!win || win->IsInnerWindow());
|
|
return win.forget();
|
|
}
|
|
|
|
nsresult
|
|
Navigator::GetPlatform(nsAString& aPlatform, bool aUsePrefOverriddenValue)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) {
|
|
const nsAdoptingString& override =
|
|
mozilla::Preferences::GetString("general.platform.override");
|
|
|
|
if (override) {
|
|
aPlatform = override;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIHttpProtocolHandler>
|
|
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// Sorry for the #if platform ugliness, but Communicator is likewise
|
|
// hardcoded and we are seeking backward compatibility here (bug 47080).
|
|
#if defined(_WIN64)
|
|
aPlatform.AssignLiteral("Win64");
|
|
#elif defined(WIN32)
|
|
aPlatform.AssignLiteral("Win32");
|
|
#elif defined(XP_MACOSX) && defined(__ppc__)
|
|
aPlatform.AssignLiteral("MacPPC");
|
|
#elif defined(XP_MACOSX)
|
|
// Always return "MacIntel", even on ARM64 macOS like Safari does.
|
|
aPlatform.AssignLiteral("MacIntel");
|
|
#else
|
|
// XXX Communicator uses compiled-in build-time string defines
|
|
// to indicate the platform it was compiled *for*, not what it is
|
|
// currently running *on* which is what this does.
|
|
nsAutoCString plat;
|
|
rv = service->GetOscpu(plat);
|
|
CopyASCIItoUTF16(plat, aPlatform);
|
|
#endif
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* static */ nsresult
|
|
Navigator::GetAppVersion(nsAString& aAppVersion, bool aUsePrefOverriddenValue)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) {
|
|
const nsAdoptingString& override =
|
|
mozilla::Preferences::GetString("general.appversion.override");
|
|
|
|
if (override) {
|
|
aAppVersion = override;
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIHttpProtocolHandler>
|
|
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsAutoCString str;
|
|
rv = service->GetAppVersion(str);
|
|
CopyASCIItoUTF16(str, aAppVersion);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
aAppVersion.AppendLiteral(" (");
|
|
|
|
rv = service->GetPlatform(str);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
AppendASCIItoUTF16(str, aAppVersion);
|
|
aAppVersion.Append(char16_t(')'));
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* static */ void
|
|
Navigator::AppName(nsAString& aAppName, bool aUsePrefOverriddenValue)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
if (aUsePrefOverriddenValue && !nsContentUtils::IsCallerChrome()) {
|
|
const nsAdoptingString& override =
|
|
mozilla::Preferences::GetString("general.appname.override");
|
|
|
|
if (override) {
|
|
aAppName = override;
|
|
return;
|
|
}
|
|
}
|
|
|
|
aAppName.AssignLiteral("Netscape");
|
|
}
|
|
|
|
void
|
|
Navigator::ClearUserAgentCache()
|
|
{
|
|
NavigatorBinding::ClearCachedUserAgentValue(this);
|
|
}
|
|
|
|
nsresult
|
|
Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
|
|
bool aIsCallerChrome,
|
|
nsAString& aUserAgent)
|
|
{
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
nsresult rv;
|
|
nsCOMPtr<nsIHttpProtocolHandler>
|
|
service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &rv));
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
nsAutoCString ua;
|
|
rv = service->GetUserAgent(ua);
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
return rv;
|
|
}
|
|
|
|
CopyASCIItoUTF16(ua, aUserAgent);
|
|
|
|
if (!aWindow || !aURI) {
|
|
return NS_OK;
|
|
}
|
|
|
|
MOZ_ASSERT(aWindow->GetDocShell());
|
|
|
|
nsCOMPtr<nsISiteSpecificUserAgent> siteSpecificUA =
|
|
do_GetService("@mozilla.org/dom/site-specific-user-agent;1");
|
|
if (!siteSpecificUA) {
|
|
return NS_OK;
|
|
}
|
|
|
|
return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent);
|
|
}
|
|
|
|
Clipboard*
|
|
Navigator::Clipboard()
|
|
{
|
|
if (!mClipboard) {
|
|
mClipboard = new dom::Clipboard(GetWindow());
|
|
}
|
|
return mClipboard;
|
|
}
|
|
|
|
} // namespace dom
|
|
} // namespace mozilla
|