Chromium Code Reviews| 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 |