Index: Source/modules/vibration/NavigatorVibration.cpp |
diff --git a/Source/modules/vibration/NavigatorVibration.cpp b/Source/modules/vibration/NavigatorVibration.cpp |
index 4e9889d56f93dc41e2f93d2260ad390c1d38d247..b6a93c6ba0d0e64a2e9b39cc1d2fdda69d4065c6 100644 |
--- a/Source/modules/vibration/NavigatorVibration.cpp |
+++ b/Source/modules/vibration/NavigatorVibration.cpp |
@@ -20,58 +20,148 @@ |
#include "config.h" |
#include "modules/vibration/NavigatorVibration.h" |
-#if ENABLE(VIBRATION) |
- |
-#include "core/dom/ExceptionCode.h" |
#include "core/page/Frame.h" |
-#include "core/page/Navigator.h" |
#include "core/page/Page.h" |
-#include "modules/vibration/Vibration.h" |
-#include "wtf/Uint32Array.h" |
+#include "public/platform/Platform.h" |
namespace WebCore { |
+// Maximum duration of a vibration is 10 seconds. |
+const unsigned kVibrationDurationMax = 10000; |
+ |
+// Maximum number of entries in a vibration pattern. |
+const unsigned kVibrationPatternLengthMax = 99; |
+ |
NavigatorVibration::NavigatorVibration() |
+ : m_timerStart(this, &NavigatorVibration::timerStartFired) |
+ , m_timerStop(this, &NavigatorVibration::timerStopFired) |
+ , m_isVibrating(false) |
{ |
} |
NavigatorVibration::~NavigatorVibration() |
{ |
+ if (m_isVibrating) |
+ cancelVibration(); |
} |
-void NavigatorVibration::vibrate(Navigator* navigator, unsigned time, ExceptionCode& ec) |
+bool NavigatorVibration::vibrate(const VibrationPattern& pattern) |
{ |
- if (!navigator->frame()->page()) |
- return; |
+ size_t length = pattern.size(); |
- if (navigator->frame()->page()->visibilityState() == PageVisibilityStateHidden) |
- return; |
+ // If the pattern is too long then abort. |
+ if (length > kVibrationPatternLengthMax) |
+ return false; |
- if (!Vibration::isActive(navigator->frame()->page())) { |
- ec = NOT_SUPPORTED_ERR; |
- return; |
+ // If any pattern entry is too long then abort. |
+ for (size_t i = 0; i < length; ++i) { |
+ if (pattern[i] > kVibrationDurationMax) |
+ return false; |
+ } |
+ |
+ m_pattern = pattern; |
+ |
+ // If the last item in the pattern is a pause then discard it. |
+ if (length && !(length % 2)) |
+ m_pattern.removeLast(); |
+ |
+ if (m_isVibrating) |
+ cancelVibration(); |
+ |
+ if (m_timerStart.isActive()) |
+ m_timerStart.stop(); |
+ |
+ if (!m_pattern.size()) |
+ return true; |
+ |
+ if (m_pattern.size() == 1 && !m_pattern[0]) { |
+ m_pattern.clear(); |
+ return true; |
} |
- Vibration::from(navigator->frame()->page())->vibrate(time); |
+ m_timerStart.startOneShot(0); |
} |
-void NavigatorVibration::vibrate(Navigator* navigator, const VibrationPattern& pattern, ExceptionCode& ec) |
+void NavigatorVibration::cancelVibration() |
{ |
- if (!navigator->frame()->page()) |
- return; |
+ m_pattern.clear(); |
+ if (m_isVibrating) { |
+ WebKit::Platform::current()->cancelVibration(); |
+ m_isVibrating = false; |
+ m_timerStop.stop(); |
+ } |
+} |
- if (navigator->frame()->page()->visibilityState() == PageVisibilityStateHidden) |
+void NavigatorVibration::suspendVibration() |
+{ |
+ if (!m_isVibrating) |
return; |
- if (!Vibration::isActive(navigator->frame()->page())) { |
- ec = NOT_SUPPORTED_ERR; |
- return; |
+ m_pattern.insert(0, m_timerStop.nextFireInterval()); |
+ m_timerStop.stop(); |
+ cancelVibration(); |
+} |
+ |
+void NavigatorVibration::resumeVibration() |
+{ |
+ m_timerStart.startOneShot(0); |
abarth-chromium
2013/06/12 20:41:27
Should we ASSERT that m_timerStart isn't active?
Michael van Ouwerkerk
2013/06/13 18:23:17
Done.
|
+} |
+ |
+void NavigatorVibration::timerStartFired(Timer<NavigatorVibration>* timer) |
+{ |
+ ASSERT_UNUSED(timer, timer == &m_timerStart); |
+ |
+ m_timerStart.stop(); |
abarth-chromium
2013/06/12 20:41:27
Is this necessary if we only use one-shot timers?
Michael van Ouwerkerk
2013/06/13 18:23:17
It doesn't seem to be. I've removed it here and in
|
+ |
+ if (m_pattern.size()) { |
+ m_isVibrating = true; |
+ WebKit::Platform::current()->vibrate(m_pattern[0]); |
+ m_timerStop.startOneShot(m_pattern[0] / 1000.0); |
+ m_pattern.remove(0); |
} |
+} |
+ |
+void NavigatorVibration::timerStopFired(Timer<NavigatorVibration>* timer) |
+{ |
+ ASSERT_UNUSED(timer, timer == &m_timerStop); |
+ |
+ m_timerStop.stop(); |
+ m_isVibrating = false; |
- Vibration::from(navigator->frame()->page())->vibrate(pattern); |
+ if (m_pattern.size()) { |
+ m_timerStart.startOneShot(m_pattern[0] / 1000.0); |
+ m_pattern.remove(0); |
+ } |
} |
-} // namespace WebCore |
+bool NavigatorVibration::vibrate(Navigator* navigator, unsigned time) |
+{ |
+ VibrationPattern pattern; |
+ pattern.append(time); |
+ return NavigatorVibration::vibrate(navigator, pattern); |
+} |
-#endif // ENABLE(VIBRATION) |
+bool NavigatorVibration::vibrate(Navigator* navigator, const VibrationPattern& pattern) |
+{ |
+ if (!navigator->frame()->page()) |
+ return false; |
+ |
+ if (navigator->frame()->page()->visibilityState() != PageVisibilityStateVisible) |
+ return false; |
+ |
+ return NavigatorVibration::from(navigator)->vibrate(pattern); |
+} |
+ |
+NavigatorVibration* NavigatorVibration::from(Navigator* navigator) |
+{ |
+ if (!Supplement<Navigator>::from(navigator, supplementName())) |
+ Supplement<Navigator>::provideTo(navigator, supplementName(), adoptPtr(new NavigatorVibration())); |
+ return static_cast<NavigatorVibration*>(Supplement<Navigator>::from(navigator, supplementName())); |
abarth-chromium
2013/06/12 20:41:27
Please use the normal pattern for these "from" fun
Michael van Ouwerkerk
2013/06/13 18:23:17
Done.
|
+} |
+ |
+const char* NavigatorVibration::supplementName() |
+{ |
+ return "NavigatorVibration"; |
+} |
+} // namespace WebCore |