From c3f15bb3e799c9da63f4fce1a9ca82eb0d230522 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Fri, 12 Jul 2013 10:35:35 -0400 Subject: [PATCH] Bug 838146 part 1. Implement WebIDL API on Navigator for the parts that are specified or are in nsIDOMNavigator. r=smaug, sr=sicking --- dom/base/Navigator.cpp | 359 +++++++++++++++++++++------ dom/base/Navigator.h | 89 ++++++- dom/bindings/Bindings.conf | 6 + dom/bindings/Codegen.py | 2 +- dom/power/PowerManager.cpp | 18 +- dom/power/PowerManager.h | 5 +- dom/webidl/Navigator.webidl | 204 +++++++++++++++ dom/webidl/WebIDL.mk | 1 + dom/workers/RuntimeService.cpp | 4 +- dom/workers/test/test_navigator.html | 3 +- 10 files changed, 598 insertions(+), 93 deletions(-) create mode 100644 dom/webidl/Navigator.webidl diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index ab23388b2858..c50c44ab5600 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -72,6 +72,9 @@ #endif #include "nsIDOMGlobalPropertyInitializer.h" +#include "nsJSUtils.h" + +#include "mozilla/dom/NavigatorBinding.h" using namespace mozilla::dom::power; @@ -362,7 +365,8 @@ Navigator::GetAppVersion(nsAString& aAppVersion) NS_IMETHODIMP Navigator::GetAppName(nsAString& aAppName) { - return NS_GetNavigatorAppName(aAppName); + NS_GetNavigatorAppName(aAppName); + return NS_OK; } /** @@ -484,31 +488,49 @@ Navigator::GetProductSub(nsAString& aProductSub) NS_IMETHODIMP Navigator::GetMimeTypes(nsISupports** aMimeTypes) +{ + ErrorResult rv; + NS_IF_ADDREF(*aMimeTypes = GetMimeTypes(rv)); + return rv.ErrorCode(); +} + +nsMimeTypeArray* +Navigator::GetMimeTypes(ErrorResult& aRv) { if (!mMimeTypes) { - NS_ENSURE_STATE(mWindow); + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } nsWeakPtr win = do_GetWeakReference(mWindow); mMimeTypes = new nsMimeTypeArray(win); } - NS_ADDREF(*aMimeTypes = mMimeTypes); - - return NS_OK; + return mMimeTypes; } NS_IMETHODIMP Navigator::GetPlugins(nsISupports** aPlugins) +{ + ErrorResult rv; + NS_IF_ADDREF(*aPlugins = static_cast(GetPlugins(rv))); + return rv.ErrorCode(); +} + +nsPluginArray* +Navigator::GetPlugins(ErrorResult& aRv) { if (!mPlugins) { - NS_ENSURE_STATE(mWindow); + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } nsWeakPtr win = do_GetWeakReference(mWindow); mPlugins = new nsPluginArray(win); mPlugins->Init(); } - NS_ADDREF(*aPlugins = static_cast(mPlugins.get())); - - return NS_OK; + return mPlugins; } // Values for the network.cookie.cookieBehavior pref are documented in @@ -518,7 +540,14 @@ Navigator::GetPlugins(nsISupports** aPlugins) NS_IMETHODIMP Navigator::GetCookieEnabled(bool* aCookieEnabled) { - *aCookieEnabled = + *aCookieEnabled = CookieEnabled(); + return NS_OK; +} + +bool +Navigator::CookieEnabled() +{ + bool cookieEnabled = (Preferences::GetInt("network.cookie.cookieBehavior", COOKIE_BEHAVIOR_REJECT) != COOKIE_BEHAVIOR_REJECT); @@ -526,12 +555,12 @@ Navigator::GetCookieEnabled(bool* aCookieEnabled) // Note that the code for getting the URI here matches that in // nsHTMLDocument::SetCookie. if (!mWindow || !mWindow->GetDocShell()) { - return NS_OK; + return cookieEnabled; } nsCOMPtr doc = mWindow->GetExtantDoc(); if (!doc) { - return NS_OK; + return cookieEnabled; } nsCOMPtr codebaseURI; @@ -540,23 +569,23 @@ Navigator::GetCookieEnabled(bool* aCookieEnabled) if (!codebaseURI) { // Not a codebase, so technically can't set cookies, but let's // just return the default value. - return NS_OK; + return cookieEnabled; } nsCOMPtr permMgr = do_GetService(NS_COOKIEPERMISSION_CONTRACTID); - NS_ENSURE_TRUE(permMgr, NS_OK); + 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, NS_OK); + NS_ENSURE_SUCCESS(rv, cookieEnabled); if (access != nsICookiePermission::ACCESS_DEFAULT) { - *aCookieEnabled = access != nsICookiePermission::ACCESS_DENY; + cookieEnabled = access != nsICookiePermission::ACCESS_DENY; } - return NS_OK; + return cookieEnabled; } NS_IMETHODIMP @@ -564,10 +593,16 @@ Navigator::GetOnLine(bool* aOnline) { NS_PRECONDITION(aOnline, "Null out param"); - *aOnline = !NS_IsOffline(); + *aOnline = OnLine(); return NS_OK; } +bool +Navigator::OnLine() +{ + return !NS_IsOffline(); +} + NS_IMETHODIMP Navigator::GetBuildID(nsAString& aBuildID) { @@ -612,14 +647,23 @@ Navigator::GetDoNotTrack(nsAString &aResult) NS_IMETHODIMP Navigator::JavaEnabled(bool* aReturn) +{ + ErrorResult rv; + *aReturn = JavaEnabled(rv); + return rv.ErrorCode(); +} + +bool +Navigator::JavaEnabled(ErrorResult& aRv) { Telemetry::AutoTimer telemetryTimer; // Return true if we have a handler for "application/x-java-vm", // otherwise return false. - *aReturn = false; - if (!mMimeTypes) { - NS_ENSURE_STATE(mWindow); + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return false; + } nsWeakPtr win = do_GetWeakReference(mWindow); mMimeTypes = new nsMimeTypeArray(win); } @@ -629,15 +673,13 @@ Navigator::JavaEnabled(bool* aReturn) nsMimeType *mimeType = mMimeTypes->NamedItem(NS_LITERAL_STRING("application/x-java-vm")); - *aReturn = mimeType && mimeType->GetEnabledPlugin(); - - return NS_OK; + return mimeType && mimeType->GetEnabledPlugin(); } NS_IMETHODIMP Navigator::TaintEnabled(bool *aReturn) { - *aReturn = false; + *aReturn = TaintEnabled(); return NS_OK; } @@ -755,11 +797,30 @@ Navigator::AddIdleObserver(nsIIdleObserver* aIdleObserver) return NS_ERROR_DOM_SECURITY_ERR; } - if (NS_FAILED(mWindow->RegisterIdleObserver(aIdleObserver))) { + AddIdleObserver(*aIdleObserver); + return NS_OK; +} + +void +Navigator::AddIdleObserver(nsIIdleObserver& aIdleObserver) +{ + // Callers (either the XPCOM method or the WebIDL binding) are responsible for + // the permission check here. + if (NS_FAILED(mWindow->RegisterIdleObserver(&aIdleObserver))) { NS_WARNING("Failed to add idle observer."); } +} - return NS_OK; +void +Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv) +{ + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return; + } + CallbackObjectHolder holder(&aIdleObserver); + nsCOMPtr obs = holder.ToXPCOMCallback(); + return AddIdleObserver(*obs); } NS_IMETHODIMP @@ -774,24 +835,35 @@ Navigator::RemoveIdleObserver(nsIIdleObserver* aIdleObserver) NS_ENSURE_ARG_POINTER(aIdleObserver); - if (NS_FAILED(mWindow->UnregisterIdleObserver(aIdleObserver))) { + RemoveIdleObserver(*aIdleObserver); + return NS_OK; +} + +void +Navigator::RemoveIdleObserver(nsIIdleObserver& aIdleObserver) +{ + // Callers (either the XPCOM method or the WebIDL binding) are responsible for + // the permission check here. + if (NS_FAILED(mWindow->UnregisterIdleObserver(&aIdleObserver))) { NS_WARNING("Failed to remove idle observer."); } - return NS_OK; +} + +void +Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv) +{ + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return; + } + CallbackObjectHolder holder(&aIdleObserver); + nsCOMPtr obs = holder.ToXPCOMCallback(); + return RemoveIdleObserver(*obs); } NS_IMETHODIMP Navigator::Vibrate(const JS::Value& aPattern, JSContext* cx) { - NS_ENSURE_STATE(mWindow); - - nsCOMPtr doc = mWindow->GetExtantDoc(); - NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); - if (doc->Hidden()) { - // Hidden documents cannot start or stop a vibration. - return NS_OK; - } - nsAutoTArray pattern; // null or undefined pattern is an error. @@ -829,10 +901,54 @@ Navigator::Vibrate(const JS::Value& aPattern, JSContext* cx) } } + ErrorResult rv; + Vibrate(pattern, rv); + return rv.ErrorCode(); +} + +void +Navigator::Vibrate(uint32_t aDuration, ErrorResult& aRv) +{ + nsAutoTArray pattern; + pattern.AppendElement(aDuration); + Vibrate(pattern, aRv); +} + +void +Navigator::Vibrate(const nsTArray& aPattern, ErrorResult& aRv) +{ + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return; + } + nsCOMPtr doc = mWindow->GetExtantDoc(); + if (!doc) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + if (doc->Hidden()) { + // Hidden documents cannot start or stop a vibration. + return; + } + + if (aPattern.Length() > sMaxVibrateListLen) { + // XXXbz this should be returning false instead + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + + for (size_t i = 0; i < aPattern.Length(); ++i) { + if (aPattern[i] > sMaxVibrateMS) { + // XXXbz this should be returning false instead + aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); + return; + } + } + // The spec says we check sVibratorEnabled after we've done the sanity // checking on the pattern. if (!sVibratorEnabled) { - return NS_OK; + return; } // Add a listener to cancel the vibration if the document becomes hidden, @@ -849,8 +965,7 @@ Navigator::Vibrate(const JS::Value& aPattern, JSContext* cx) } gVibrateWindowListener = new VibrateWindowListener(mWindow, doc); - hal::Vibrate(pattern, mWindow); - return NS_OK; + hal::Vibrate(aPattern, mWindow); } //***************************************************************************** @@ -1040,34 +1155,35 @@ NS_IMETHODIMP Navigator::GetDeviceStorages(const nsAString &aType, nsIVariant** NS_IMETHODIMP Navigator::GetGeolocation(nsIDOMGeoGeolocation** _retval) { - NS_ENSURE_ARG_POINTER(_retval); - *_retval = nullptr; + ErrorResult rv; + NS_IF_ADDREF(*_retval = GetGeolocation(rv)); + return rv.ErrorCode(); +} +Geolocation* +Navigator::GetGeolocation(ErrorResult& aRv) +{ if (!Preferences::GetBool("geo.enabled", true)) { - return NS_OK; + return nullptr; } if (mGeolocation) { - NS_ADDREF(*_retval = mGeolocation); - return NS_OK; + return mGeolocation; } if (!mWindow || !mWindow->GetOuterWindow() || !mWindow->GetDocShell()) { - return NS_ERROR_FAILURE; + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; } mGeolocation = new Geolocation(); - if (!mGeolocation) { - return NS_ERROR_FAILURE; - } - if (NS_FAILED(mGeolocation->Init(mWindow->GetOuterWindow()))) { mGeolocation = nullptr; - return NS_ERROR_FAILURE; + aRv.Throw(NS_ERROR_FAILURE); + return nullptr; } - NS_ADDREF(*_retval = mGeolocation); - return NS_OK; + return mGeolocation; } //***************************************************************************** @@ -1148,50 +1264,85 @@ NS_IMETHODIMP Navigator::GetMozNotification(nsISupports** aRetVal) NS_IMETHODIMP Navigator::GetBattery(nsISupports** aBattery) { - if (!mBatteryManager) { - *aBattery = nullptr; + ErrorResult rv; + NS_IF_ADDREF(*aBattery = GetBattery(rv)); + return rv.ErrorCode(); +} - NS_ENSURE_STATE(mWindow); - NS_ENSURE_TRUE(mWindow->GetDocShell(), NS_OK); +battery::BatteryManager* +Navigator::GetBattery(ErrorResult& aRv) +{ + if (!mBatteryManager) { + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr); mBatteryManager = new battery::BatteryManager(); mBatteryManager->Init(mWindow); } - NS_ADDREF(*aBattery = mBatteryManager); - - return NS_OK; + return mBatteryManager; } NS_IMETHODIMP Navigator::GetMozPower(nsIDOMMozPowerManager** aPower) { - *aPower = nullptr; + if (!PowerManager::CheckPermission(mWindow)) { + *aPower = nullptr; + return NS_OK; + } + ErrorResult rv; + NS_IF_ADDREF(*aPower = GetMozPower(rv)); + return rv.ErrorCode(); +} +nsIDOMMozPowerManager* +Navigator::GetMozPower(ErrorResult& aRv) +{ + // Callers (either the XPCOM method or the WebIDL binding) are responsible for + // the permission check here. if (!mPowerManager) { - NS_ENSURE_STATE(mWindow); - mPowerManager = PowerManager::CheckPermissionAndCreateInstance(mWindow); - NS_ENSURE_TRUE(mPowerManager, NS_OK); + 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); + } } - nsCOMPtr power(mPowerManager); - power.forget(aPower); - - return NS_OK; + return mPowerManager; } NS_IMETHODIMP Navigator::RequestWakeLock(const nsAString &aTopic, nsIDOMMozWakeLock **aWakeLock) { - NS_ENSURE_STATE(mWindow); + ErrorResult rv; + *aWakeLock = RequestWakeLock(aTopic, rv).get(); + return rv.ErrorCode(); +} - *aWakeLock = nullptr; +already_AddRefed +Navigator::RequestWakeLock(const nsAString &aTopic, ErrorResult& aRv) +{ + if (!mWindow) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } nsCOMPtr pmService = do_GetService(POWERMANAGERSERVICE_CONTRACTID); - NS_ENSURE_TRUE(pmService, NS_OK); + // Maybe it went away for some reason... Or maybe we're just called + // from our XPCOM method. + NS_ENSURE_TRUE(pmService, nullptr); - return pmService->NewWakeLock(aTopic, mWindow, aWakeLock); + nsCOMPtr wakelock; + aRv = pmService->NewWakeLock(aTopic, mWindow, getter_AddRefs(wakelock)); + return wakelock.forget(); } //***************************************************************************** @@ -1604,7 +1755,14 @@ Navigator::OnNavigation() bool Navigator::CheckPermission(const char* type) { - if (!mWindow) { + return CheckPermission(mWindow, type); +} + +/* static */ +bool +Navigator::CheckPermission(nsPIDOMWindow* aWindow, const char* aType) +{ + if (!aWindow) { return false; } @@ -1613,7 +1771,7 @@ Navigator::CheckPermission(const char* type) NS_ENSURE_TRUE(permMgr, false); uint32_t permission = nsIPermissionManager::DENY_ACTION; - permMgr->TestPermissionFromWindow(mWindow, type, &permission); + permMgr->TestPermissionFromWindow(aWindow, aType, &permission); return permission == nsIPermissionManager::ALLOW_ACTION; } @@ -1637,6 +1795,53 @@ Navigator::GetMozAudioChannelManager(nsISupports** aAudioChannelManager) } #endif +/* static */ +bool +Navigator::HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */) +{ + return battery::BatteryManager::HasSupport(); +} + +/* static */ +bool +Navigator::HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal) +{ + nsCOMPtr win = GetWindowFromGlobal(aGlobal); + return win && PowerManager::CheckPermission(win); +} + +/* static */ +bool +Navigator::HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal) +{ + if (!nsContentUtils::IsIdleObserverAPIEnabled()) { + return false; + } + + nsCOMPtr win = GetWindowFromGlobal(aGlobal); + return CheckPermission(win, "idle"); +} + +/* static */ +bool +Navigator::HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */) +{ + nsCOMPtr pmService = + do_GetService(POWERMANAGERSERVICE_CONTRACTID); + // No service means no wake lock support + return !!pmService; +} + +/* static */ +already_AddRefed +Navigator::GetWindowFromGlobal(JSObject* aGlobal) +{ + nsCOMPtr win = + do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal)); + MOZ_ASSERT(!win || win->IsInnerWindow()); + return win.forget(); +} + } // namespace dom } // namespace mozilla @@ -1735,7 +1940,7 @@ NS_GetNavigatorAppVersion(nsAString& aAppVersion) return rv; } -nsresult +void NS_GetNavigatorAppName(nsAString& aAppName) { if (!nsContentUtils::IsCallerChrome()) { @@ -1744,10 +1949,8 @@ NS_GetNavigatorAppName(nsAString& aAppName) if (override) { aAppName = override; - return NS_OK; } } aAppName.AssignLiteral("Netscape"); - return NS_OK; } diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index 0646ac62c885..4b6c220b8346 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -69,6 +69,8 @@ class nsIDOMTelephony; // Navigator: Script "navigator" object //***************************************************************************** +void NS_GetNavigatorAppName(nsAString& aAppName); + namespace mozilla { namespace dom { @@ -79,6 +81,7 @@ class BatteryManager; class DesktopNotificationCenter; class SmsManager; class MobileMessageManager; +class MozIdleObserver; namespace icc { #ifdef MOZ_B2G_RIL @@ -192,7 +195,7 @@ public: static void Init(); void Invalidate(); - nsPIDOMWindow *GetWindow() + nsPIDOMWindow *GetWindow() const { return mWindow; } @@ -218,8 +221,91 @@ public: NS_DECL_NSIDOMNAVIGATORCAMERA + // WebIDL API + void GetAppName(nsString& aAppName) + { + NS_GetNavigatorAppName(aAppName); + } + void GetAppVersion(nsString& aAppVersion, ErrorResult& aRv) + { + aRv = GetAppVersion(aAppVersion); + } + void GetPlatform(nsString& aPlatform, ErrorResult& aRv) + { + aRv = GetPlatform(aPlatform); + } + void GetUserAgent(nsString& aUserAgent, ErrorResult& aRv) + { + aRv = GetUserAgent(aUserAgent); + } + // The XPCOM GetProduct is OK + // The XPCOM GetLanguage is OK + bool OnLine(); + void RegisterProtocolHandler(const nsAString& aScheme, const nsAString& aURL, + const nsAString& aTitle, ErrorResult& rv) + { + rv = RegisterProtocolHandler(aScheme, aURL, aTitle); + } + void RegisterContentHandler(const nsAString& aMIMEType, const nsAString& aURL, + const nsAString& aTitle, ErrorResult& rv) + { + rv = RegisterContentHandler(aMIMEType, aURL, aTitle); + } + nsMimeTypeArray* GetMimeTypes(ErrorResult& aRv); + nsPluginArray* GetPlugins(ErrorResult& aRv); + // The XPCOM GetDoNotTrack is ok + Geolocation* GetGeolocation(ErrorResult& aRv); + battery::BatteryManager* GetBattery(ErrorResult& aRv); + void Vibrate(uint32_t aDuration, ErrorResult& aRv); + void Vibrate(const nsTArray& aDuration, ErrorResult& aRv); + void GetAppCodeName(nsString& aAppCodeName, ErrorResult& aRv) + { + aRv = GetAppCodeName(aAppCodeName); + } + void GetOscpu(nsString& aOscpu, ErrorResult& aRv) + { + aRv = GetOscpu(aOscpu); + } + // The XPCOM GetVendor is OK + // The XPCOM GetVendorSub is OK + // The XPCOM GetProductSub is OK + bool CookieEnabled(); + void GetBuildID(nsString& aBuildID, ErrorResult& aRv) + { + aRv = GetBuildID(aBuildID); + } + nsIDOMMozPowerManager* GetMozPower(ErrorResult& aRv); + bool JavaEnabled(ErrorResult& aRv); + bool TaintEnabled() + { + return false; + } + void AddIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv); + void RemoveIdleObserver(MozIdleObserver& aObserver, ErrorResult& aRv); + already_AddRefed RequestWakeLock(const nsAString &aTopic, + ErrorResult& aRv); + + // WebIDL helper methods + static bool HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */); + static bool HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal); + static bool HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal); + static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */); + nsPIDOMWindow* GetParentObject() const + { + return GetWindow(); + } + private: bool CheckPermission(const char* type); + static bool CheckPermission(nsPIDOMWindow* aWindow, const char* aType); + // GetWindowFromGlobal returns the inner window for this global, if + // any, else null. + static already_AddRefed GetWindowFromGlobal(JSObject* aGlobal); + + // Methods to common up the XPCOM and WebIDL implementations of + // Add/RemoveIdleObserver. + void AddIdleObserver(nsIIdleObserver& aIdleObserver); + void RemoveIdleObserver(nsIIdleObserver& aIdleObserver); nsRefPtr mMimeTypes; nsRefPtr mPlugins; @@ -258,6 +344,5 @@ private: nsresult NS_GetNavigatorUserAgent(nsAString& aUserAgent); nsresult NS_GetNavigatorPlatform(nsAString& aPlatform); nsresult NS_GetNavigatorAppVersion(nsAString& aAppVersion); -nsresult NS_GetNavigatorAppName(nsAString& aAppName); #endif // mozilla_dom_Navigator_h diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index dcb8488af4c9..4dd3004eb30f 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -711,6 +711,10 @@ DOMInterfaces = { 'previousSibling', 'nextSibling' ] }, +'Navigator': { + 'register': False, +}, + 'Node': { 'nativeType': 'nsINode', 'concrete': False, @@ -1706,6 +1710,7 @@ addExternalIface('MozBoxObject', nativeType='nsIBoxObject') addExternalIface('MozControllers', nativeType='nsIControllers') addExternalIface('MozFrameLoader', nativeType='nsIFrameLoader', notflattened=True) addExternalIface('MozObserver', nativeType='nsIObserver', notflattened=True) +addExternalIface('MozPowerManager', headerFile='nsIDOMPowerManager.h') addExternalIface('MozRDFCompositeDataSource', nativeType='nsIRDFCompositeDataSource', notflattened=True) addExternalIface('MozRDFResource', nativeType='nsIRDFResource', notflattened=True) @@ -1713,6 +1718,7 @@ addExternalIface('MozTreeBoxObject', nativeType='nsITreeBoxObject', notflattened=True) addExternalIface('MozTreeColumn', nativeType='nsITreeColumn', headerFile='nsITreeColumns.h') +addExternalIface('MozWakeLock', headerFile='nsIDOMWakeLock.h') addExternalIface('MozXULTemplateBuilder', nativeType='nsIXULTemplateBuilder') addExternalIface('nsIControllers', nativeType='nsIControllers') addExternalIface('nsIInputStreamCallback', nativeType='nsIInputStreamCallback', diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 8f7279939dfb..dba2cb8d726b 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -3732,7 +3732,7 @@ def convertConstIDLValueToJSVal(value): return "JSVAL_TRUE" if value.value else "JSVAL_FALSE" if tag in [IDLType.Tags.float, IDLType.Tags.double]: return "DOUBLE_TO_JSVAL(%s)" % (value.value) - raise TypeError("Const value of unhandled type: " + value.type) + raise TypeError("Const value of unhandled type: %s" % value.type) class CGArgumentConverter(CGThing): """ diff --git a/dom/power/PowerManager.cpp b/dom/power/PowerManager.cpp index 139a0f8639c5..e13f47862a8d 100644 --- a/dom/power/PowerManager.cpp +++ b/dom/power/PowerManager.cpp @@ -179,22 +179,26 @@ PowerManager::SetCpuSleepAllowed(bool aAllowed) return NS_OK; } -already_AddRefed -PowerManager::CheckPermissionAndCreateInstance(nsPIDOMWindow* aWindow) +bool +PowerManager::CheckPermission(nsPIDOMWindow* aWindow) { nsCOMPtr permMgr = do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); - NS_ENSURE_TRUE(permMgr, nullptr); + NS_ENSURE_TRUE(permMgr, false); uint32_t permission = nsIPermissionManager::DENY_ACTION; permMgr->TestPermissionFromWindow(aWindow, "power", &permission); - if (permission != nsIPermissionManager::ALLOW_ACTION) { - return nullptr; - } + return permission == nsIPermissionManager::ALLOW_ACTION; +} +already_AddRefed +PowerManager::CreateInstance(nsPIDOMWindow* aWindow) +{ nsRefPtr powerManager = new PowerManager(); - powerManager->Init(aWindow); + if (NS_FAILED(powerManager->Init(aWindow))) { + powerManager = nullptr; + } return powerManager.forget(); } diff --git a/dom/power/PowerManager.h b/dom/power/PowerManager.h index 4bec150a665b..a68456eb8cbd 100644 --- a/dom/power/PowerManager.h +++ b/dom/power/PowerManager.h @@ -33,8 +33,9 @@ public: nsresult Init(nsIDOMWindow *aWindow); nsresult Shutdown(); - static already_AddRefed - CheckPermissionAndCreateInstance(nsPIDOMWindow*); + static bool CheckPermission(nsPIDOMWindow*); + + static already_AddRefed CreateInstance(nsPIDOMWindow*); private: diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl new file mode 100644 index 000000000000..e0ae7f682f0e --- /dev/null +++ b/dom/webidl/Navigator.webidl @@ -0,0 +1,204 @@ +/* -*- Mode: IDL; 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/. + * + * The origin of this IDL file is + * http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object + * http://www.w3.org/TR/tracking-dnt/ + * http://www.w3.org/TR/geolocation-API/#geolocation_interface + * http://www.w3.org/TR/battery-status/#navigatorbattery-interface + * http://www.w3.org/TR/vibration/#vibration-interface + * + * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and + * Opera Software ASA. You are granted a license to use, reproduce + * and create derivative works of this document. + */ + +interface MozPowerManager; +interface MozWakeLock; + +// http://www.whatwg.org/specs/web-apps/current-work/#the-navigator-object +[HeaderFile="Navigator.h"] +interface Navigator { + // objects implementing this interface also implement the interfaces given below +}; +Navigator implements NavigatorID; +Navigator implements NavigatorLanguage; +Navigator implements NavigatorOnLine; +Navigator implements NavigatorContentUtils; +Navigator implements NavigatorStorageUtils; + +[NoInterfaceObject] +interface NavigatorID { + readonly attribute DOMString appName; + [Throws] + readonly attribute DOMString appVersion; + [Throws] + readonly attribute DOMString platform; + [Throws] + readonly attribute DOMString userAgent; + + // Spec has this as a const, but that's wrong because it should not + // be on the interface object. + //const DOMString product = "Gecko"; // for historical reasons + readonly attribute DOMString product; +}; + +[NoInterfaceObject] +interface NavigatorLanguage { + readonly attribute DOMString? language; +}; + +[NoInterfaceObject] +interface NavigatorOnLine { + readonly attribute boolean onLine; +}; + +[NoInterfaceObject] +interface NavigatorContentUtils { + // content handler registration + [Throws] + void registerProtocolHandler(DOMString scheme, DOMString url, DOMString title); + [Throws] + void registerContentHandler(DOMString mimeType, DOMString url, DOMString title); + // NOT IMPLEMENTED + //DOMString isProtocolHandlerRegistered(DOMString scheme, DOMString url); + //DOMString isContentHandlerRegistered(DOMString mimeType, DOMString url); + //void unregisterProtocolHandler(DOMString scheme, DOMString url); + //void unregisterContentHandler(DOMString mimeType, DOMString url); +}; + +[NoInterfaceObject] +interface NavigatorStorageUtils { + // NOT IMPLEMENTED + //void yieldForStorageUpdates(); +}; + +// Things that definitely need to be in the spec and and are not for some +// reason. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=22406 +partial interface Navigator { + [Throws] + readonly attribute MimeTypeArray mimeTypes; + [Throws] + readonly attribute PluginArray plugins; +}; + +// http://www.w3.org/TR/tracking-dnt/ sort of +partial interface Navigator { + readonly attribute DOMString doNotTrack; +}; + +// http://www.w3.org/TR/geolocation-API/#geolocation_interface +[NoInterfaceObject] +interface NavigatorGeolocation { + // XXXbz This should perhaps be controleld by the "geo.enabled" pref, instead + // of checking it in the C++. Let's not for now to reduce risk. + // Also, we violate the spec as a result, since we can return null. See bug + // 884921. + [Throws] + readonly attribute Geolocation? geolocation; +}; +Navigator implements NavigatorGeolocation; + +// http://www.w3.org/TR/battery-status/#navigatorbattery-interface +[NoInterfaceObject] +interface NavigatorBattery { + // XXXbz Per spec this should be non-nullable, but we return null in + // torn-down windows. See bug 884925. + [Throws, Func="Navigator::HasBatterySupport"] + readonly attribute BatteryManager? battery; +}; +Navigator implements NavigatorBattery; + +// http://www.w3.org/TR/vibration/#vibration-interface +partial interface Navigator { + // We don't support sequences in unions yet + //boolean vibrate ((unsigned long or sequence) pattern); + // XXXbz also, per spec we should be returning a boolean, and we just don't. + // See bug 884935. + [Throws] + void vibrate(unsigned long duration); + [Throws] + void vibrate(sequence pattern); +}; + +// Mozilla-specific extensions + +callback interface MozIdleObserver { + // Time is in seconds and is read only when idle observers are added + // and removed. + readonly attribute unsigned long time; + void onidle(); + void onactive(); +}; + +// nsIDOMNavigator +partial interface Navigator { + // WebKit/Blink/Trident/Presto support this (hardcoded "Mozilla"). + [Throws] + readonly attribute DOMString appCodeName; + [Throws] + readonly attribute DOMString oscpu; + // WebKit/Blink support this; Trident/Presto do not. + readonly attribute DOMString vendor; + // WebKit/Blink supports this (hardcoded ""); Trident/Presto do not. + readonly attribute DOMString vendorSub; + // WebKit/Blink supports this (hardcoded "20030107"); Trident/Presto don't + readonly attribute DOMString productSub; + // WebKit/Blink/Trident/Presto support this. + readonly attribute boolean cookieEnabled; + [Throws] + readonly attribute DOMString buildID; + [Throws, Func="Navigator::HasPowerSupport"] + readonly attribute MozPowerManager mozPower; + + // WebKit/Blink/Trident/Presto support this. + [Throws] + boolean javaEnabled(); + // Everyone but WebKit/Blink supports this. See bug 679971. + boolean taintEnabled(); + + /** + * Navigator requests to add an idle observer to the existing window. + */ + [Throws, Func="Navigator::HasIdleSupport"] + void addIdleObserver(MozIdleObserver aIdleObserver); + + /** + * Navigator requests to remove an idle observer from the existing window. + */ + [Throws, Func="Navigator::HasIdleSupport"] + void removeIdleObserver(MozIdleObserver aIdleObserver); + + /** + * Request a wake lock for a resource. + * + * A page holds a wake lock to request that a resource not be turned + * off (or otherwise made unavailable). + * + * The topic is the name of a resource that might be made unavailable for + * various reasons. For example, on a mobile device the power manager might + * decide to turn off the screen after a period of idle time to save power. + * + * The resource manager checks the lock state of a topic before turning off + * the associated resource. For example, a page could hold a lock on the + * "screen" topic to prevent the screensaver from appearing or the screen + * from turning off. + * + * The resource manager defines what each topic means and sets policy. For + * example, the resource manager might decide to ignore 'screen' wake locks + * held by pages which are not visible. + * + * One topic can be locked multiple times; it is considered released only when + * all locks on the topic have been released. + * + * The returned nsIDOMMozWakeLock object is a token of the lock. You can + * unlock the lock via the object's |unlock| method. The lock is released + * automatically when its associated window is unloaded. + * + * @param aTopic resource name + */ + [Throws, Func="Navigator::HasWakeLockSupport"] + MozWakeLock requestWakeLock(DOMString aTopic); +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 2763dce7fde4..7b361ef72eda 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -191,6 +191,7 @@ webidl_files = \ MozTimeManager.webidl \ MutationEvent.webidl \ MutationObserver.webidl \ + Navigator.webidl \ NetDashboard.webidl \ Node.webidl \ NodeFilter.webidl \ diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index b9e6ff26ff8e..0ad7f4aba0e2 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -1158,8 +1158,8 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate) } else { if (!mNavigatorStringsLoaded) { - if (NS_FAILED(NS_GetNavigatorAppName(mNavigatorStrings.mAppName)) || - NS_FAILED(NS_GetNavigatorAppVersion(mNavigatorStrings.mAppVersion)) || + NS_GetNavigatorAppName(mNavigatorStrings.mAppName); + if (NS_FAILED(NS_GetNavigatorAppVersion(mNavigatorStrings.mAppVersion)) || NS_FAILED(NS_GetNavigatorPlatform(mNavigatorStrings.mPlatform)) || NS_FAILED(NS_GetNavigatorUserAgent(mNavigatorStrings.mUserAgent))) { JS_ReportError(aCx, "Failed to load navigator strings!"); diff --git a/dom/workers/test/test_navigator.html b/dom/workers/test/test_navigator.html index 689c1d9630a3..ccace0e446d1 100644 --- a/dom/workers/test/test_navigator.html +++ b/dom/workers/test/test_navigator.html @@ -35,7 +35,8 @@ Tests of DOM Worker Navigator return; } - is(navigator[args.name], args.value, "Mismatched navigator string!"); + is(navigator[args.name], args.value, + "Mismatched navigator string for " + args.name + "!"); }; worker.onerror = function(event) {