/hal/Hal.cpp

http://github.com/zpao/v8monkey · C++ · 424 lines · 315 code · 77 blank · 32 comment · 28 complexity · b24a3887614dc93743e7a09d56726487 MD5 · raw file

  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* vim: set sw=2 ts=8 et ft=cpp : */
  3. /* This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. #include "Hal.h"
  7. #include "HalImpl.h"
  8. #include "HalSandbox.h"
  9. #include "mozilla/Util.h"
  10. #include "nsThreadUtils.h"
  11. #include "nsXULAppAPI.h"
  12. #include "mozilla/Observer.h"
  13. #include "nsIDOMDocument.h"
  14. #include "nsIDOMWindow.h"
  15. #include "mozilla/Services.h"
  16. #include "nsIWebNavigation.h"
  17. #include "nsITabChild.h"
  18. #include "nsIDocShell.h"
  19. #include "mozilla/ClearOnShutdown.h"
  20. #include "WindowIdentifier.h"
  21. using namespace mozilla::services;
  22. #define PROXY_IF_SANDBOXED(_call) \
  23. do { \
  24. if (InSandbox()) { \
  25. hal_sandbox::_call; \
  26. } else { \
  27. hal_impl::_call; \
  28. } \
  29. } while (0)
  30. #define RETURN_PROXY_IF_SANDBOXED(_call) \
  31. do { \
  32. if (InSandbox()) { \
  33. return hal_sandbox::_call; \
  34. } else { \
  35. return hal_impl::_call; \
  36. } \
  37. } while (0)
  38. namespace mozilla {
  39. namespace hal {
  40. PRLogModuleInfo *sHalLog = PR_LOG_DEFINE("hal");
  41. namespace {
  42. void
  43. AssertMainThread()
  44. {
  45. MOZ_ASSERT(NS_IsMainThread());
  46. }
  47. bool
  48. InSandbox()
  49. {
  50. return GeckoProcessType_Content == XRE_GetProcessType();
  51. }
  52. bool
  53. WindowIsActive(nsIDOMWindow *window)
  54. {
  55. NS_ENSURE_TRUE(window, false);
  56. nsCOMPtr<nsIDOMDocument> doc;
  57. window->GetDocument(getter_AddRefs(doc));
  58. NS_ENSURE_TRUE(doc, false);
  59. bool hidden = true;
  60. doc->GetMozHidden(&hidden);
  61. return !hidden;
  62. }
  63. nsAutoPtr<WindowIdentifier::IDArrayType> gLastIDToVibrate;
  64. void InitLastIDToVibrate()
  65. {
  66. gLastIDToVibrate = new WindowIdentifier::IDArrayType();
  67. ClearOnShutdown(&gLastIDToVibrate);
  68. }
  69. } // anonymous namespace
  70. void
  71. Vibrate(const nsTArray<uint32>& pattern, nsIDOMWindow* window)
  72. {
  73. Vibrate(pattern, WindowIdentifier(window));
  74. }
  75. void
  76. Vibrate(const nsTArray<uint32>& pattern, const WindowIdentifier &id)
  77. {
  78. AssertMainThread();
  79. // Only active windows may start vibrations. If |id| hasn't gone
  80. // through the IPC layer -- that is, if our caller is the outside
  81. // world, not hal_proxy -- check whether the window is active. If
  82. // |id| has gone through IPC, don't check the window's visibility;
  83. // only the window corresponding to the bottommost process has its
  84. // visibility state set correctly.
  85. if (!id.HasTraveledThroughIPC() && !WindowIsActive(id.GetWindow())) {
  86. HAL_LOG(("Vibrate: Window is inactive, dropping vibrate."));
  87. return;
  88. }
  89. if (InSandbox()) {
  90. hal_sandbox::Vibrate(pattern, id);
  91. }
  92. else {
  93. if (!gLastIDToVibrate)
  94. InitLastIDToVibrate();
  95. *gLastIDToVibrate = id.AsArray();
  96. HAL_LOG(("Vibrate: Forwarding to hal_impl."));
  97. // hal_impl doesn't need |id|. Send it an empty id, which will
  98. // assert if it's used.
  99. hal_impl::Vibrate(pattern, WindowIdentifier());
  100. }
  101. }
  102. void
  103. CancelVibrate(nsIDOMWindow* window)
  104. {
  105. CancelVibrate(WindowIdentifier(window));
  106. }
  107. void
  108. CancelVibrate(const WindowIdentifier &id)
  109. {
  110. AssertMainThread();
  111. // Although only active windows may start vibrations, a window may
  112. // cancel its own vibration even if it's no longer active.
  113. //
  114. // After a window is marked as inactive, it sends a CancelVibrate
  115. // request. We want this request to cancel a playing vibration
  116. // started by that window, so we certainly don't want to reject the
  117. // cancellation request because the window is now inactive.
  118. //
  119. // But it could be the case that, after this window became inactive,
  120. // some other window came along and started a vibration. We don't
  121. // want this window's cancellation request to cancel that window's
  122. // actively-playing vibration!
  123. //
  124. // To solve this problem, we keep track of the id of the last window
  125. // to start a vibration, and only accepts cancellation requests from
  126. // the same window. All other cancellation requests are ignored.
  127. if (InSandbox()) {
  128. hal_sandbox::CancelVibrate(id);
  129. }
  130. else if (*gLastIDToVibrate == id.AsArray()) {
  131. // Don't forward our ID to hal_impl. It doesn't need it, and we
  132. // don't want it to be tempted to read it. The empty identifier
  133. // will assert if it's used.
  134. HAL_LOG(("CancelVibrate: Forwarding to hal_impl."));
  135. hal_impl::CancelVibrate(WindowIdentifier());
  136. }
  137. }
  138. template <class InfoType>
  139. class ObserversManager
  140. {
  141. public:
  142. void AddObserver(Observer<InfoType>* aObserver) {
  143. if (!mObservers) {
  144. mObservers = new mozilla::ObserverList<InfoType>();
  145. }
  146. mObservers->AddObserver(aObserver);
  147. if (mObservers->Length() == 1) {
  148. EnableNotifications();
  149. }
  150. }
  151. void RemoveObserver(Observer<InfoType>* aObserver) {
  152. MOZ_ASSERT(mObservers);
  153. mObservers->RemoveObserver(aObserver);
  154. if (mObservers->Length() == 0) {
  155. DisableNotifications();
  156. delete mObservers;
  157. mObservers = 0;
  158. mHasValidCache = false;
  159. }
  160. }
  161. InfoType GetCurrentInformation() {
  162. if (mHasValidCache) {
  163. return mInfo;
  164. }
  165. mHasValidCache = true;
  166. GetCurrentInformationInternal(&mInfo);
  167. return mInfo;
  168. }
  169. void CacheInformation(const InfoType& aInfo) {
  170. mHasValidCache = true;
  171. mInfo = aInfo;
  172. }
  173. void BroadcastCachedInformation() {
  174. MOZ_ASSERT(mObservers);
  175. mObservers->Broadcast(mInfo);
  176. }
  177. protected:
  178. virtual void EnableNotifications() = 0;
  179. virtual void DisableNotifications() = 0;
  180. virtual void GetCurrentInformationInternal(InfoType*) = 0;
  181. private:
  182. mozilla::ObserverList<InfoType>* mObservers;
  183. InfoType mInfo;
  184. bool mHasValidCache;
  185. };
  186. class BatteryObserversManager : public ObserversManager<BatteryInformation>
  187. {
  188. protected:
  189. void EnableNotifications() {
  190. PROXY_IF_SANDBOXED(EnableBatteryNotifications());
  191. }
  192. void DisableNotifications() {
  193. PROXY_IF_SANDBOXED(DisableBatteryNotifications());
  194. }
  195. void GetCurrentInformationInternal(BatteryInformation* aInfo) {
  196. PROXY_IF_SANDBOXED(GetCurrentBatteryInformation(aInfo));
  197. }
  198. };
  199. static BatteryObserversManager sBatteryObservers;
  200. class NetworkObserversManager : public ObserversManager<NetworkInformation>
  201. {
  202. protected:
  203. void EnableNotifications() {
  204. PROXY_IF_SANDBOXED(EnableNetworkNotifications());
  205. }
  206. void DisableNotifications() {
  207. PROXY_IF_SANDBOXED(DisableNetworkNotifications());
  208. }
  209. void GetCurrentInformationInternal(NetworkInformation* aInfo) {
  210. PROXY_IF_SANDBOXED(GetCurrentNetworkInformation(aInfo));
  211. }
  212. };
  213. static NetworkObserversManager sNetworkObservers;
  214. void
  215. RegisterBatteryObserver(BatteryObserver* aObserver)
  216. {
  217. AssertMainThread();
  218. sBatteryObservers.AddObserver(aObserver);
  219. }
  220. void
  221. UnregisterBatteryObserver(BatteryObserver* aObserver)
  222. {
  223. AssertMainThread();
  224. sBatteryObservers.RemoveObserver(aObserver);
  225. }
  226. void
  227. GetCurrentBatteryInformation(BatteryInformation* aInfo)
  228. {
  229. AssertMainThread();
  230. *aInfo = sBatteryObservers.GetCurrentInformation();
  231. }
  232. void
  233. NotifyBatteryChange(const BatteryInformation& aInfo)
  234. {
  235. AssertMainThread();
  236. sBatteryObservers.CacheInformation(aInfo);
  237. sBatteryObservers.BroadcastCachedInformation();
  238. }
  239. bool GetScreenEnabled()
  240. {
  241. AssertMainThread();
  242. RETURN_PROXY_IF_SANDBOXED(GetScreenEnabled());
  243. }
  244. void SetScreenEnabled(bool enabled)
  245. {
  246. AssertMainThread();
  247. PROXY_IF_SANDBOXED(SetScreenEnabled(enabled));
  248. }
  249. double GetScreenBrightness()
  250. {
  251. AssertMainThread();
  252. RETURN_PROXY_IF_SANDBOXED(GetScreenBrightness());
  253. }
  254. void SetScreenBrightness(double brightness)
  255. {
  256. AssertMainThread();
  257. PROXY_IF_SANDBOXED(SetScreenBrightness(clamped(brightness, 0.0, 1.0)));
  258. }
  259. bool SetLight(LightType light, const hal::LightConfiguration& aConfig)
  260. {
  261. AssertMainThread();
  262. RETURN_PROXY_IF_SANDBOXED(SetLight(light, aConfig));
  263. }
  264. bool GetLight(LightType light, hal::LightConfiguration* aConfig)
  265. {
  266. AssertMainThread();
  267. RETURN_PROXY_IF_SANDBOXED(GetLight(light, aConfig));
  268. }
  269. void
  270. EnableSensorNotifications(SensorType aSensor) {
  271. AssertMainThread();
  272. PROXY_IF_SANDBOXED(EnableSensorNotifications(aSensor));
  273. }
  274. void
  275. DisableSensorNotifications(SensorType aSensor) {
  276. AssertMainThread();
  277. PROXY_IF_SANDBOXED(DisableSensorNotifications(aSensor));
  278. }
  279. typedef mozilla::ObserverList<SensorData> SensorObserverList;
  280. static SensorObserverList *gSensorObservers = NULL;
  281. static SensorObserverList &
  282. GetSensorObservers(SensorType sensor_type) {
  283. MOZ_ASSERT(sensor_type < NUM_SENSOR_TYPE);
  284. if(gSensorObservers == NULL)
  285. gSensorObservers = new SensorObserverList[NUM_SENSOR_TYPE];
  286. return gSensorObservers[sensor_type];
  287. }
  288. void
  289. RegisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
  290. SensorObserverList &observers = GetSensorObservers(aSensor);
  291. AssertMainThread();
  292. observers.AddObserver(aObserver);
  293. if(observers.Length() == 1) {
  294. EnableSensorNotifications(aSensor);
  295. }
  296. }
  297. void
  298. UnregisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) {
  299. SensorObserverList &observers = GetSensorObservers(aSensor);
  300. AssertMainThread();
  301. observers.RemoveObserver(aObserver);
  302. if(observers.Length() == 0) {
  303. DisableSensorNotifications(aSensor);
  304. }
  305. }
  306. void
  307. NotifySensorChange(const SensorData &aSensorData) {
  308. SensorObserverList &observers = GetSensorObservers(aSensorData.sensor());
  309. AssertMainThread();
  310. observers.Broadcast(aSensorData);
  311. }
  312. void
  313. RegisterNetworkObserver(NetworkObserver* aObserver)
  314. {
  315. AssertMainThread();
  316. sNetworkObservers.AddObserver(aObserver);
  317. }
  318. void
  319. UnregisterNetworkObserver(NetworkObserver* aObserver)
  320. {
  321. AssertMainThread();
  322. sNetworkObservers.RemoveObserver(aObserver);
  323. }
  324. void
  325. GetCurrentNetworkInformation(NetworkInformation* aInfo)
  326. {
  327. AssertMainThread();
  328. *aInfo = sNetworkObservers.GetCurrentInformation();
  329. }
  330. void
  331. NotifyNetworkChange(const NetworkInformation& aInfo)
  332. {
  333. sNetworkObservers.CacheInformation(aInfo);
  334. sNetworkObservers.BroadcastCachedInformation();
  335. }
  336. void Reboot()
  337. {
  338. AssertMainThread();
  339. PROXY_IF_SANDBOXED(Reboot());
  340. }
  341. void PowerOff()
  342. {
  343. AssertMainThread();
  344. PROXY_IF_SANDBOXED(PowerOff());
  345. }
  346. } // namespace hal
  347. } // namespace mozilla